diff options
author | dim <dim@FreeBSD.org> | 2015-05-27 20:44:45 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-05-27 20:44:45 +0000 |
commit | fae9061769fe2114f1a7875c781cc369ff303a11 (patch) | |
tree | 50a603f7e1932cd42f58e26687ce907933014db0 /contrib/llvm/tools/clang/lib/Sema | |
parent | 5ef8fd3549d38e883a31881636be3dc2a275de20 (diff) | |
parent | 3191b2b32a96e1a6ee833fcca73e5c8e0c67ba65 (diff) | |
download | FreeBSD-src-fae9061769fe2114f1a7875c781cc369ff303a11.zip FreeBSD-src-fae9061769fe2114f1a7875c781cc369ff303a11.tar.gz |
Merge clang trunk r238337 from ^/vendor/clang/dist, resolve conflicts,
and preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
43 files changed, 7019 insertions, 3053 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp index f666a9b..d697ecb 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -117,6 +117,7 @@ static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC); } +namespace { /// \brief Warn on logical operator errors in CFGBuilder class LogicalErrorHandler : public CFGCallback { Sema &S; @@ -138,7 +139,7 @@ public: return false; } - void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) { + void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override { if (HasMacroID(B)) return; @@ -147,7 +148,8 @@ public: << DiagRange << isAlwaysTrue; } - void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue) { + void compareBitwiseEquality(const BinaryOperator *B, + bool isAlwaysTrue) override { if (HasMacroID(B)) return; @@ -156,7 +158,7 @@ public: << DiagRange << isAlwaysTrue; } }; - +} // namespace //===----------------------------------------------------------------------===// // Check for infinite self-recursion in functions @@ -1332,9 +1334,7 @@ class UninitValsDiagReporter : public UninitVariablesHandler { public: UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {} - ~UninitValsDiagReporter() { - flushDiagnostics(); - } + ~UninitValsDiagReporter() override { flushDiagnostics(); } MappedType &getUses(const VarDecl *vd) { if (!uses) @@ -1438,7 +1438,7 @@ struct SortDiagBySourceLocation { //===----------------------------------------------------------------------===// namespace clang { namespace threadSafety { - +namespace { class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { Sema &S; DiagList Warnings; @@ -1662,9 +1662,8 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { } } - - virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg, - SourceLocation Loc) override { + void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg, + SourceLocation Loc) override { PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_acquire_requires_negative_cap) << Kind << LockName << Neg); @@ -1679,6 +1678,19 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { Warnings.push_back(DelayedDiag(Warning, getNotes())); } + void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name, + SourceLocation Loc) override { + PartialDiagnosticAt Warning(Loc, + S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name); + Warnings.push_back(DelayedDiag(Warning, getNotes())); + } + + void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override { + PartialDiagnosticAt Warning(Loc, + S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name); + Warnings.push_back(DelayedDiag(Warning, getNotes())); + } + void enterFunction(const FunctionDecl* FD) override { CurrentFunction = FD; } @@ -1687,9 +1699,9 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { CurrentFunction = 0; } }; - -} -} +} // namespace +} // namespace threadSafety +} // namespace clang //===----------------------------------------------------------------------===// // -Wconsumed @@ -1704,7 +1716,7 @@ class ConsumedWarningsHandler : public ConsumedWarningsHandlerBase { DiagList Warnings; public: - + ConsumedWarningsHandler(Sema &S) : S(S) {} void emitDiagnostics() override { @@ -1981,7 +1993,8 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getLocStart())) Reporter.setVerbose(true); - threadSafety::runThreadSafetyAnalysis(AC, Reporter); + threadSafety::runThreadSafetyAnalysis(AC, Reporter, + &S.ThreadSafetyDeclCache); Reporter.emitDiagnostics(); } diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp index b2dc2d7..69ae4f0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -251,19 +251,16 @@ const char *CodeCompletionString::getTypedText() const { return nullptr; } -const char *CodeCompletionAllocator::CopyString(StringRef String) { - char *Mem = (char *)Allocate(String.size() + 1, 1); - std::copy(String.begin(), String.end(), Mem); - Mem[String.size()] = 0; - return Mem; -} - -const char *CodeCompletionAllocator::CopyString(Twine String) { +const char *CodeCompletionAllocator::CopyString(const Twine &String) { + SmallString<128> Data; + StringRef Ref = String.toStringRef(Data); // FIXME: It would be more efficient to teach Twine to tell us its size and // then add a routine there to fill in an allocated char* with the contents // of the string. - SmallString<128> Data; - return CopyString(String.toStringRef(Data)); + char *Mem = (char *)Allocate(Ref.size() + 1, 1); + std::copy(Ref.begin(), Ref.end(), Mem); + Mem[Ref.size()] = 0; + return Mem; } StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { @@ -483,6 +480,31 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, } } +// This function is used solely to preserve the former presentation of overloads +// by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString +// needs to be improved for printing the newer and more detailed overload +// chunks. +static std::string getOverloadAsString(const CodeCompletionString &CCS) { + std::string Result; + llvm::raw_string_ostream OS(Result); + + for (auto &C : CCS) { + switch (C.Kind) { + case CodeCompletionString::CK_Informative: + case CodeCompletionString::CK_ResultType: + OS << "[#" << C.Text << "#]"; + break; + + case CodeCompletionString::CK_CurrentParameter: + OS << "<#" << C.Text << "#>"; + break; + + default: OS << C.Text; break; + } + } + return OS.str(); +} + void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, unsigned CurrentArg, @@ -491,8 +513,9 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, for (unsigned I = 0; I != NumCandidates; ++I) { if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(CurrentArg, SemaRef, - getAllocator(), CCTUInfo)) { - OS << "OVERLOAD: " << CCS->getAsString() << "\n"; + getAllocator(), CCTUInfo, + includeBriefComments())) { + OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n"; } } } diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index 349bb32..1e7fc75 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -983,11 +983,18 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli getSpecifierName((TST)TypeSpecType, Policy)); } - // Only 'short' is valid with vector bool. (PIM 2.1) - if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short)) + // Only 'short' and 'long long' are valid with vector bool. (PIM 2.1) + if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) && + (TypeSpecWidth != TSW_longlong)) Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec) << getSpecifierName((TSW)TypeSpecWidth); + // vector bool long long requires VSX support. + if ((TypeSpecWidth == TSW_longlong) && + (!PP.getTargetInfo().hasFeature("vsx")) && + (!PP.getTargetInfo().hasFeature("power8-vector"))) + Diag(D, TSTLoc, diag::err_invalid_vector_long_long_decl_spec); + // Elements of vector bool are interpreted as unsigned. (PIM 2.1) if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) || (TypeSpecWidth != TSW_unspecified)) @@ -1214,7 +1221,10 @@ void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, const char *&PrevSpec) { + if (!FirstLocation.isValid()) + FirstLocation = Loc; LastLocation = Loc; + LastSpecifier = VS; if (Specifiers & VS) { PrevSpec = getSpecifierName(VS); diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp index 664a6b1..ceea04f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp @@ -35,6 +35,8 @@ DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD, case Sema::AD_Unavailable: DD.Kind = Unavailable; break; + case Sema::AD_Partial: + llvm_unreachable("AD_Partial diags should not be delayed"); } DD.Triggered = false; DD.Loc = Loc; diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp index 6586fb3..53263ba 100644 --- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp @@ -98,7 +98,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S, bool AllowInlineNamespace) const { Ctx = Ctx->getRedeclContext(); - if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) { + if (Ctx->isFunctionOrMethod() || (S && S->isFunctionPrototypeScope())) { // Ignore the scopes associated within transparent declaration contexts. while (S->getEntity() && S->getEntity()->isTransparentContext()) S = S->getParent(); @@ -266,6 +266,11 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) { // If the declarations are redeclarations of each other, keep the newest one. if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) { + // If we're adding an imported declaration, don't replace another imported + // declaration. + if (Existing->isFromASTFile() && New->isFromASTFile()) + return DMK_Different; + // If either of these is the most recent declaration, use it. Decl *MostRecent = Existing->getMostRecentDecl(); if (Existing == MostRecent) diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index fd75c02..aac28be 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -338,6 +338,36 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) return; } + case Stmt::SEHTryStmtClass: { + SEHTryStmt *TS = cast<SEHTryStmt>(S); + unsigned newParentScope; + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_seh_try, + diag::note_exits_seh_try, + TS->getSourceRange().getBegin())); + if (Stmt *TryBlock = TS->getTryBlock()) + BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1)); + + // Jump from __except or __finally into the __try are not allowed either. + if (SEHExceptStmt *Except = TS->getExceptHandler()) { + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_seh_except, + diag::note_exits_seh_except, + Except->getSourceRange().getBegin())); + BuildScopeInformation(Except->getBlock(), + (newParentScope = Scopes.size()-1)); + } else if (SEHFinallyStmt *Finally = TS->getFinallyHandler()) { + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_seh_finally, + diag::note_exits_seh_finally, + Finally->getSourceRange().getBegin())); + BuildScopeInformation(Finally->getBlock(), + (newParentScope = Scopes.size()-1)); + } + + return; + } + default: break; } @@ -417,7 +447,8 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) unsigned newParentScope; // Disallow jumps into the protected statement of an @synchronized, but // allow jumps into the object expression it protects. - if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){ + if (ObjCAtSynchronizedStmt *AS = + dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)) { // Recursively walk the AST for the @synchronized object expr, it is // evaluated in the normal scope. BuildScopeInformation(AS->getSynchExpr(), ParentScope); @@ -434,14 +465,16 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) } // Disallow jumps into the protected statement of an @autoreleasepool. - if (ObjCAutoreleasePoolStmt *AS = dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)){ - // Recursively walk the AST for the @autoreleasepool part, protected by a new - // scope. + if (ObjCAutoreleasePoolStmt *AS = + dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)) { + // Recursively walk the AST for the @autoreleasepool part, protected by a + // new scope. Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_objc_autoreleasepool, diag::note_exits_objc_autoreleasepool, AS->getAtLoc())); - BuildScopeInformation(AS->getSubStmt(), (newParentScope = Scopes.size()-1)); + BuildScopeInformation(AS->getSubStmt(), + (newParentScope = Scopes.size() - 1)); continue; } @@ -756,6 +789,18 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, // Common case: exactly the same scope, which is fine. if (FromScope == ToScope) return; + // Warn on gotos out of __finally blocks. + if (isa<GotoStmt>(From) || isa<IndirectGotoStmt>(From)) { + // If FromScope > ToScope, FromScope is more nested and the jump goes to a + // less nested scope. Check if it crosses a __finally along the way. + for (unsigned I = FromScope; I > ToScope; I = Scopes[I].ParentScope) { + if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) { + S.Diag(From->getLocStart(), diag::warn_jump_out_of_seh_finally); + break; + } + } + } + unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope); // It's okay to jump out from a nested scope. diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 449ddf4..9ecb5a7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -86,6 +86,14 @@ CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers( return nullptr; } +CXXCtorInitializer ** +MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) { + for (auto *S : Sources) + if (auto *R = S->GetExternalCXXCtorInitializers(Offset)) + return R; + return nullptr; +} + bool MultiplexExternalSemaSource:: FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { bool AnyDeclsFound = false; @@ -204,7 +212,15 @@ void MultiplexExternalSemaSource::ReadUndefinedButUsed( for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->ReadUndefinedButUsed(Undefined); } - + +void MultiplexExternalSemaSource::ReadMismatchingDeleteExpressions( + llvm::MapVector<FieldDecl *, + llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> & + Exprs) { + for (auto &Source : Sources) + Source->ReadMismatchingDeleteExpressions(Exprs); +} + bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){ for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->LookupUnqualified(R, S); @@ -236,24 +252,12 @@ void MultiplexExternalSemaSource::ReadExtVectorDecls( Sources[i]->ReadExtVectorDecls(Decls); } -void MultiplexExternalSemaSource::ReadDynamicClasses( - SmallVectorImpl<CXXRecordDecl*> &Decls) { - for(size_t i = 0; i < Sources.size(); ++i) - Sources[i]->ReadDynamicClasses(Decls); -} - void MultiplexExternalSemaSource::ReadUnusedLocalTypedefNameCandidates( llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) { for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->ReadUnusedLocalTypedefNameCandidates(Decls); } -void MultiplexExternalSemaSource::ReadLocallyScopedExternCDecls( - SmallVectorImpl<NamedDecl*> &Decls) { - for(size_t i = 0; i < Sources.size(); ++i) - Sources[i]->ReadLocallyScopedExternCDecls(Decls); -} - void MultiplexExternalSemaSource::ReadReferencedSelectors( SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) { for(size_t i = 0; i < Sources.size(); ++i) @@ -280,7 +284,7 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations( } void MultiplexExternalSemaSource::ReadLateParsedTemplates( - llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) { + llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) { for (size_t i = 0; i < Sources.size(); ++i) Sources[i]->ReadLateParsedTemplates(LPTMap); } diff --git a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp index 6c79778..7c70048 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp @@ -38,7 +38,8 @@ void Scope::Init(Scope *parent, unsigned flags) { FnParent = parent->FnParent; BlockParent = parent->BlockParent; TemplateParamParent = parent->TemplateParamParent; - MSLocalManglingParent = parent->MSLocalManglingParent; + MSLastManglingParent = parent->MSLastManglingParent; + MSCurManglingNumber = getMSLastManglingNumber(); if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope | FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) == 0) @@ -47,9 +48,10 @@ void Scope::Init(Scope *parent, unsigned flags) { Depth = 0; PrototypeDepth = 0; PrototypeIndex = 0; - MSLocalManglingParent = FnParent = BlockParent = nullptr; + MSLastManglingParent = FnParent = BlockParent = nullptr; TemplateParamParent = nullptr; - MSLocalManglingNumber = 1; + MSLastManglingNumber = 1; + MSCurManglingNumber = 1; } // If this scope is a function or contains breaks/continues, remember it. @@ -57,8 +59,9 @@ void Scope::Init(Scope *parent, unsigned flags) { // The MS mangler uses the number of scopes that can hold declarations as // part of an external name. if (Flags & (ClassScope | FnScope)) { - MSLocalManglingNumber = getMSLocalManglingNumber(); - MSLocalManglingParent = this; + MSLastManglingNumber = getMSLastManglingNumber(); + MSLastManglingParent = this; + MSCurManglingNumber = 1; } if (flags & BreakScope) BreakParent = this; if (flags & ContinueScope) ContinueParent = this; @@ -78,7 +81,7 @@ void Scope::Init(Scope *parent, unsigned flags) { else if ((flags & EnumScope)) ; // Don't increment for enum scopes. else - incrementMSLocalManglingNumber(); + incrementMSManglingNumber(); } DeclsInScope.clear(); @@ -185,6 +188,9 @@ void Scope::dumpImpl(raw_ostream &OS) const { } else if (Flags & SEHTryScope) { OS << "SEHTryScope"; Flags &= ~SEHTryScope; + } else if (Flags & SEHExceptScope) { + OS << "SEHExceptScope"; + Flags &= ~SEHExceptScope; } else if (Flags & OpenMPDirectiveScope) { OS << "OpenMPDirectiveScope"; Flags &= ~OpenMPDirectiveScope; @@ -206,12 +212,13 @@ void Scope::dumpImpl(raw_ostream &OS) const { OS << "Parent: (clang::Scope*)" << Parent << '\n'; OS << "Depth: " << Depth << '\n'; - OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n'; + OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n'; + OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n'; if (const DeclContext *DC = getEntity()) OS << "Entity : (clang::DeclContext*)" << DC << '\n'; if (NRVO.getInt()) - OS << "NRVO not allowed"; + OS << "NRVO not allowed\n"; else if (NRVO.getPointer()) OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n'; } diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp index 63ef3b2..f80eadf 100644 --- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp @@ -33,6 +33,8 @@ void FunctionScopeInfo::Clear() { ObjCWarnForNoDesignatedInitChain = false; ObjCIsSecondaryInit = false; ObjCWarnForNoInitDelegation = false; + FirstCXXTryLoc = SourceLocation(); + FirstSEHTryLoc = SourceLocation(); SwitchStack.clear(); Returns.clear(); diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index b9aaf16..50edc42 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -99,10 +99,11 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, GlobalNewDeleteDeclared(false), TUKind(TUKind), NumSFINAEErrors(0), + CachedFakeTopLevelModule(nullptr), AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr), DisableTypoCorrection(false), - TyposCorrected(0), AnalysisWarnings(*this), + TyposCorrected(0), AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr), CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) { @@ -122,9 +123,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context); - ExprEvalContexts.push_back( - ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, - false, nullptr, false)); + ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false); FunctionScopes.push_back(new FunctionScopeInfo(Diags)); @@ -195,8 +194,9 @@ void Sema::Initialize() { } // Initialize Microsoft "predefined C++ types". - if (PP.getLangOpts().MSVCCompat && PP.getLangOpts().CPlusPlus) { - if (IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end()) + if (PP.getLangOpts().MSVCCompat) { + if (PP.getLangOpts().CPlusPlus && + IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end()) PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class), TUScope); @@ -213,6 +213,29 @@ void Sema::Initialize() { addImplicitTypedef("image3d_t", Context.OCLImage3dTy); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); + if (getLangOpts().OpenCLVersion >= 200) { + addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy)); + addImplicitTypedef("atomic_uint", + Context.getAtomicType(Context.UnsignedIntTy)); + addImplicitTypedef("atomic_long", Context.getAtomicType(Context.LongTy)); + addImplicitTypedef("atomic_ulong", + Context.getAtomicType(Context.UnsignedLongTy)); + addImplicitTypedef("atomic_float", + Context.getAtomicType(Context.FloatTy)); + addImplicitTypedef("atomic_double", + Context.getAtomicType(Context.DoubleTy)); + // OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as + // 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide. + addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy)); + addImplicitTypedef("atomic_intptr_t", + Context.getAtomicType(Context.getIntPtrType())); + addImplicitTypedef("atomic_uintptr_t", + Context.getAtomicType(Context.getUIntPtrType())); + addImplicitTypedef("atomic_size_t", + Context.getAtomicType(Context.getSizeType())); + addImplicitTypedef("atomic_ptrdiff_t", + Context.getAtomicType(Context.getPointerDiffType())); + } } DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list"); @@ -243,6 +266,8 @@ Sema::~Sema() { if (isMultiplexExternalSource) delete ExternalSource; + threadSafety::threadSafetyCleanup(ThreadSafetyDeclCache); + // Destroys data sharing attributes stack for OpenMP DestroyDataSharingAttributesStack(); @@ -337,18 +362,6 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, if (ExprTy == TypeTy) return 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 = E->getType(); - if (const PointerType *Pointer = T->getAs<PointerType>()) - T = Pointer->getPointeeType(); - if (const RecordType *RecordTy = T->getAs<RecordType>()) - MarkVTableUsed(E->getLocStart(), - cast<CXXRecordDecl>(RecordTy->getDecl())); - } - if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) { if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { ImpCast->setType(Ty); @@ -512,14 +525,8 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() { SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs; ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs); - for (unsigned I = 0, N = WeakIDs.size(); I != N; ++I) { - llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator Pos - = WeakUndeclaredIdentifiers.find(WeakIDs[I].first); - if (Pos != WeakUndeclaredIdentifiers.end()) - continue; - - WeakUndeclaredIdentifiers.insert(WeakIDs[I]); - } + for (auto &WeakID : WeakIDs) + WeakUndeclaredIdentifiers.insert(WeakID); } @@ -632,22 +639,6 @@ void Sema::ActOnEndOfTranslationUnit() { if (TUKind != TU_Prefix) { DiagnoseUseOfUnimplementedSelectors(); - // If any dynamic classes have their key function defined within - // this translation unit, then those vtables are considered "used" and must - // be emitted. - for (DynamicClassesType::iterator I = DynamicClasses.begin(ExternalSource), - E = DynamicClasses.end(); - I != E; ++I) { - assert(!(*I)->isDependentType() && - "Should not see dependent types here!"); - if (const CXXMethodDecl *KeyFunction = - Context.getCurrentKeyFunction(*I)) { - const FunctionDecl *Definition = nullptr; - if (KeyFunction->hasBody(Definition)) - MarkVTableUsed(Definition->getLocation(), *I, true); - } - } - // If DefinedUsedVTables ends up marking any virtual member functions it // might lead to more pending template instantiations, which we then need // to instantiate. @@ -679,6 +670,8 @@ void Sema::ActOnEndOfTranslationUnit() { // All delayed member exception specs should be checked or we end up accepting // incompatible declarations. + // FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to + // write out the lists to the AST file (if any). assert(DelayedDefaultedMemberExceptionSpecs.empty()); assert(DelayedExceptionSpecChecks.empty()); @@ -696,16 +689,13 @@ void Sema::ActOnEndOfTranslationUnit() { } // Check for #pragma weak identifiers that were never declared - // FIXME: This will cause diagnostics to be emitted in a non-determinstic - // order! Iterating over a densemap like this is bad. LoadExternalWeakUndeclaredIdentifiers(); - for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator - I = WeakUndeclaredIdentifiers.begin(), - E = WeakUndeclaredIdentifiers.end(); I != E; ++I) { - if (I->second.getUsed()) continue; + for (auto WeakID : WeakUndeclaredIdentifiers) { + if (WeakID.second.getUsed()) + continue; - Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared) - << I->first; + Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared) + << WeakID.first; } if (LangOpts.CPlusPlus11 && @@ -871,6 +861,17 @@ void Sema::ActOnEndOfTranslationUnit() { } } + if (!Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) { + if (ExternalSource) + ExternalSource->ReadMismatchingDeleteExpressions(DeleteExprs); + for (const auto &DeletedFieldInfo : DeleteExprs) { + for (const auto &DeleteExprLoc : DeletedFieldInfo.second) { + AnalyzeDeleteExprMismatch(DeletedFieldInfo.first, DeleteExprLoc.first, + DeleteExprLoc.second); + } + } + } + // Check we've noticed that we're no longer parsing the initializer for every // variable. If we miss cases, then at best we have a performance issue and // at worst a rejects-valid bug. @@ -1230,6 +1231,9 @@ void ExternalSemaSource::ReadUndefinedButUsed( llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) { } +void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector< + FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {} + void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { SourceLocation Loc = this->Loc; if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation(); @@ -1478,3 +1482,8 @@ CapturedRegionScopeInfo *Sema::getCurCapturedRegion() { return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back()); } + +const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> & +Sema::getMismatchingDeleteExpressions() const { + return DeleteExprs; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp index 37240c2..0e973cc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -1462,7 +1462,7 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, case AR_inaccessible: return Sema::AR_inaccessible; case AR_dependent: return Sema::AR_dependent; } - llvm_unreachable("falling off end"); + llvm_unreachable("invalid access result"); } void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp index 7629797..5a29bad 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp @@ -131,7 +131,7 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { if (MSStructPragmaOn) - RD->addAttr(MsStructAttr::CreateImplicit(Context)); + RD->addAttr(MSStructAttr::CreateImplicit(Context)); // FIXME: We should merge AddAlignmentAttributesForRecord with // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes @@ -422,6 +422,9 @@ void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation, if (Action & PSK_Pop && Stack->Stack.empty()) Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName << "stack empty"; + if (SegmentName && + !checkSectionName(SegmentName->getLocStart(), SegmentName->getString())) + return; Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp index 64222fb..5973500 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp @@ -62,6 +62,11 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) { bool Sema::CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee) { + // The CUDADisableTargetCallChecks short-circuits this check: we assume all + // cross-target calls are valid. + if (getLangOpts().CUDADisableTargetCallChecks) + return false; + CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller), CalleeTarget = IdentifyCUDATarget(Callee); @@ -92,9 +97,21 @@ bool Sema::CheckCUDATarget(const FunctionDecl *Caller, if (Caller->isImplicit()) return false; bool InDeviceMode = getLangOpts().CUDAIsDevice; - if ((InDeviceMode && CalleeTarget != CFT_Device) || - (!InDeviceMode && CalleeTarget != CFT_Host)) + if (!InDeviceMode && CalleeTarget != CFT_Host) + return true; + if (InDeviceMode && CalleeTarget != CFT_Device) { + // Allow host device functions to call host functions if explicitly + // requested. + if (CalleeTarget == CFT_Host && + getLangOpts().CUDAAllowHostCallsFromHostDevice) { + Diag(Caller->getLocation(), + diag::warn_host_calls_from_host_device) + << Callee->getNameAsString() << Caller->getNameAsString(); + return false; + } + return true; + } } return false; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index 3e56e67..9e146ed 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -218,6 +218,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, // Fixed enum types are complete, but they aren't valid as scopes // until we see a definition, so awkwardly pull out this special // case. + // FIXME: The definition might not be visible; complain if it is not. const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType); if (!enumType || enumType->getDecl()->isCompleteDefinition()) return false; @@ -282,7 +283,11 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc, /// \brief Determines whether the given declaration is an valid acceptable /// result for name lookup of a nested-name-specifier. -bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) { +/// \param SD Declaration checked for nested-name-specifier. +/// \param IsExtension If not null and the declaration is accepted as an +/// extension, the pointed variable is assigned true. +bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD, + bool *IsExtension) { if (!SD) return false; @@ -298,14 +303,23 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) { QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); if (T->isDependentType()) return true; - else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { - if (TD->getUnderlyingType()->isRecordType() || - (Context.getLangOpts().CPlusPlus11 && - TD->getUnderlyingType()->isEnumeralType())) + if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { + if (TD->getUnderlyingType()->isRecordType()) return true; - } else if (isa<RecordDecl>(SD) || - (Context.getLangOpts().CPlusPlus11 && isa<EnumDecl>(SD))) + if (TD->getUnderlyingType()->isEnumeralType()) { + if (Context.getLangOpts().CPlusPlus11) + return true; + if (IsExtension) + *IsExtension = true; + } + } else if (isa<RecordDecl>(SD)) { return true; + } else if (isa<EnumDecl>(SD)) { + if (Context.getLangOpts().CPlusPlus11) + return true; + if (IsExtension) + *IsExtension = true; + } return false; } @@ -599,7 +613,13 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, } NamedDecl *SD = Found.getAsSingle<NamedDecl>(); - if (isAcceptableNestedNameSpecifier(SD)) { + bool IsExtension = false; + bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, &IsExtension); + if (!AcceptSpec && IsExtension) { + AcceptSpec = true; + Diag(IdentifierLoc, diag::ext_nested_name_spec_is_enum); + } + if (AcceptSpec) { if (!ObjectType.isNull() && !ObjectTypeSearchedInScope && !getLangOpts().CPlusPlus11) { // C++03 [basic.lookup.classref]p4: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp index a4c2d9b..091e779 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp @@ -389,6 +389,33 @@ static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, S.Diag(opRange.getBegin(), msg) << castType << src->getType() << destType << opRange << src->getSourceRange(); + + // Detect if both types are (ptr to) class, and note any incompleteness. + int DifferentPtrness = 0; + QualType From = destType; + if (auto Ptr = From->getAs<PointerType>()) { + From = Ptr->getPointeeType(); + DifferentPtrness++; + } + QualType To = src->getType(); + if (auto Ptr = To->getAs<PointerType>()) { + To = Ptr->getPointeeType(); + DifferentPtrness--; + } + if (!DifferentPtrness) { + auto RecFrom = From->getAs<RecordType>(); + auto RecTo = To->getAs<RecordType>(); + if (RecFrom && RecTo) { + auto DeclFrom = RecFrom->getAsCXXRecordDecl(); + if (!DeclFrom->isCompleteDefinition()) + S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete) + << DeclFrom->getDeclName(); + auto DeclTo = RecTo->getAsCXXRecordDecl(); + if (!DeclTo->isCompleteDefinition()) + S.Diag(DeclTo->getLocation(), diag::note_type_incomplete) + << DeclTo->getDeclName(); + } + } } /// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes, @@ -665,12 +692,6 @@ void CastOperation::CheckDynamicCast() { } Kind = CK_DerivedToBase; - - // If we are casting to or through a virtual base class, we need a - // vtable. - if (Self.BasePathInvolvesVirtualBase(BasePath)) - Self.MarkVTableUsed(OpRange.getBegin(), - cast<CXXRecordDecl>(SrcRecord->getDecl())); return; } @@ -682,8 +703,6 @@ void CastOperation::CheckDynamicCast() { << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); SrcExpr = ExprError(); } - Self.MarkVTableUsed(OpRange.getBegin(), - cast<CXXRecordDecl>(SrcRecord->getDecl())); // dynamic_cast is not available with -fno-rtti. // As an exception, dynamic_cast to void* is available because it doesn't @@ -1087,6 +1106,14 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, if (!CStyle && Self.CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind)) return TC_Success; + + // See if it looks like the user is trying to convert between + // related record types, and select a better diagnostic if so. + if (auto SrcPointer = SrcType->getAs<PointerType>()) + if (auto DestPointer = DestType->getAs<PointerType>()) + if (SrcPointer->getPointeeType()->getAs<RecordType>() && + DestPointer->getPointeeType()->getAs<RecordType>()) + msg = diag::err_bad_cxx_cast_unrelated_class; // We tried everything. Everything! Nothing works! :-( return TC_NotApplicable; @@ -1790,8 +1817,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, // can be explicitly converted to an rvalue of type "pointer to member // of Y of type T2" if T1 and T2 are both function types or both object // types. - if (DestMemPtr->getPointeeType()->isFunctionType() != - SrcMemPtr->getPointeeType()->isFunctionType()) + if (DestMemPtr->isMemberFunctionPointer() != + SrcMemPtr->isMemberFunctionPointer()) return TC_NotApplicable; // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 6ab957e..23a6fc3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -184,7 +184,7 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { return true; } - QualType ReturnTy = CE->getCallReturnType(); + QualType ReturnTy = CE->getCallReturnType(S.Context); QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() }; QualType BuiltinTy = S.Context.getFunctionType( ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo()); @@ -202,6 +202,28 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { return false; } +static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall, + Scope::ScopeFlags NeededScopeFlags, + unsigned DiagID) { + // Scopes aren't available during instantiation. Fortunately, builtin + // functions cannot be template args so they cannot be formed through template + // instantiation. Therefore checking once during the parse is sufficient. + if (!SemaRef.ActiveTemplateInstantiations.empty()) + return false; + + Scope *S = SemaRef.getCurScope(); + while (S && !S->isSEHExceptScope()) + S = S->getParent(); + if (!S || !(S->getFlags() & NeededScopeFlags)) { + auto *DRE = cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); + SemaRef.Diag(TheCall->getExprLoc(), DiagID) + << DRE->getDecl()->getIdentifier(); + return true; + } + + return false; +} + ExprResult Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall) { @@ -301,6 +323,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinSetjmp(TheCall)) return ExprError(); break; + case Builtin::BI_setjmp: + case Builtin::BI_setjmpex: + if (checkArgCount(*this, TheCall, 1)) + return true; + break; case Builtin::BI__builtin_classify_type: if (checkArgCount(*this, TheCall, 1)) return true; @@ -465,6 +492,35 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinCallWithStaticChain(*this, TheCall)) return ExprError(); break; + + case Builtin::BI__exception_code: + case Builtin::BI_exception_code: { + if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHExceptScope, + diag::err_seh___except_block)) + return ExprError(); + break; + } + case Builtin::BI__exception_info: + case Builtin::BI_exception_info: { + if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHFilterScope, + diag::err_seh___except_filter)) + return ExprError(); + break; + } + + case Builtin::BI__GetExceptionInfo: + if (checkArgCount(*this, TheCall, 1)) + return ExprError(); + + if (CheckCXXThrowOperand( + TheCall->getLocStart(), + Context.getExceptionObjectType(FDecl->getParamDecl(0)->getType()), + TheCall)) + return ExprError(); + + TheCall->setType(Context.VoidPtrTy); + break; + } // Since the target specific builtins for each arch overlap, only check those @@ -490,11 +546,21 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; + case llvm::Triple::systemz: + if (CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; case llvm::Triple::x86: case llvm::Triple::x86_64: if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + if (CheckPPCBuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; default: break; } @@ -557,7 +623,10 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, case NeonTypeFlags::Poly16: return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy; case NeonTypeFlags::Poly64: - return Context.UnsignedLongTy; + if (IsInt64Long) + return Context.UnsignedLongTy; + else + return Context.UnsignedLongLongTy; case NeonTypeFlags::Poly128: break; case NeonTypeFlags::Float16: @@ -839,15 +908,161 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return SemaBuiltinConstantArgRange(TheCall, i, l, u); } +bool Sema::CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + unsigned i = 0, l = 0, u = 0; + bool Is64BitBltin = BuiltinID == PPC::BI__builtin_divde || + BuiltinID == PPC::BI__builtin_divdeu || + BuiltinID == PPC::BI__builtin_bpermd; + bool IsTarget64Bit = Context.getTargetInfo() + .getTypeWidth(Context + .getTargetInfo() + .getIntPtrType()) == 64; + bool IsBltinExtDiv = BuiltinID == PPC::BI__builtin_divwe || + BuiltinID == PPC::BI__builtin_divweu || + BuiltinID == PPC::BI__builtin_divde || + BuiltinID == PPC::BI__builtin_divdeu; + + if (Is64BitBltin && !IsTarget64Bit) + return Diag(TheCall->getLocStart(), diag::err_64_bit_builtin_32_bit_tgt) + << TheCall->getSourceRange(); + + if ((IsBltinExtDiv && !Context.getTargetInfo().hasFeature("extdiv")) || + (BuiltinID == PPC::BI__builtin_bpermd && + !Context.getTargetInfo().hasFeature("bpermd"))) + return Diag(TheCall->getLocStart(), diag::err_ppc_builtin_only_on_pwr7) + << TheCall->getSourceRange(); + + switch (BuiltinID) { + default: return false; + case PPC::BI__builtin_altivec_crypto_vshasigmaw: + case PPC::BI__builtin_altivec_crypto_vshasigmad: + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) || + SemaBuiltinConstantArgRange(TheCall, 2, 0, 15); + case PPC::BI__builtin_tbegin: + case PPC::BI__builtin_tend: i = 0; l = 0; u = 1; break; + case PPC::BI__builtin_tsr: i = 0; l = 0; u = 7; break; + case PPC::BI__builtin_tabortwc: + case PPC::BI__builtin_tabortdc: i = 0; l = 0; u = 31; break; + case PPC::BI__builtin_tabortwci: + case PPC::BI__builtin_tabortdci: + return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) || + SemaBuiltinConstantArgRange(TheCall, 2, 0, 31); + } + return SemaBuiltinConstantArgRange(TheCall, i, l, u); +} + +bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + if (BuiltinID == SystemZ::BI__builtin_tabort) { + Expr *Arg = TheCall->getArg(0); + llvm::APSInt AbortCode(32); + if (Arg->isIntegerConstantExpr(AbortCode, Context) && + AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256) + return Diag(Arg->getLocStart(), diag::err_systemz_invalid_tabort_code) + << Arg->getSourceRange(); + } + + // For intrinsics which take an immediate value as part of the instruction, + // range check them here. + unsigned i = 0, l = 0, u = 0; + switch (BuiltinID) { + default: return false; + case SystemZ::BI__builtin_s390_lcbb: i = 1; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_verimb: + case SystemZ::BI__builtin_s390_verimh: + case SystemZ::BI__builtin_s390_verimf: + case SystemZ::BI__builtin_s390_verimg: i = 3; l = 0; u = 255; break; + case SystemZ::BI__builtin_s390_vfaeb: + case SystemZ::BI__builtin_s390_vfaeh: + case SystemZ::BI__builtin_s390_vfaef: + case SystemZ::BI__builtin_s390_vfaebs: + case SystemZ::BI__builtin_s390_vfaehs: + case SystemZ::BI__builtin_s390_vfaefs: + case SystemZ::BI__builtin_s390_vfaezb: + case SystemZ::BI__builtin_s390_vfaezh: + case SystemZ::BI__builtin_s390_vfaezf: + case SystemZ::BI__builtin_s390_vfaezbs: + case SystemZ::BI__builtin_s390_vfaezhs: + case SystemZ::BI__builtin_s390_vfaezfs: i = 2; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_vfidb: + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 15) || + SemaBuiltinConstantArgRange(TheCall, 2, 0, 15); + case SystemZ::BI__builtin_s390_vftcidb: i = 1; l = 0; u = 4095; break; + case SystemZ::BI__builtin_s390_vlbb: i = 1; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_vpdi: i = 2; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_vsldb: i = 2; l = 0; u = 15; break; + case SystemZ::BI__builtin_s390_vstrcb: + case SystemZ::BI__builtin_s390_vstrch: + case SystemZ::BI__builtin_s390_vstrcf: + case SystemZ::BI__builtin_s390_vstrczb: + case SystemZ::BI__builtin_s390_vstrczh: + case SystemZ::BI__builtin_s390_vstrczf: + case SystemZ::BI__builtin_s390_vstrcbs: + case SystemZ::BI__builtin_s390_vstrchs: + case SystemZ::BI__builtin_s390_vstrcfs: + case SystemZ::BI__builtin_s390_vstrczbs: + case SystemZ::BI__builtin_s390_vstrczhs: + case SystemZ::BI__builtin_s390_vstrczfs: i = 3; l = 0; u = 15; break; + } + return SemaBuiltinConstantArgRange(TheCall, i, l, u); +} + bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { unsigned i = 0, l = 0, u = 0; switch (BuiltinID) { default: return false; case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break; + case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break; + case X86::BI__builtin_ia32_vpermil2pd: + case X86::BI__builtin_ia32_vpermil2pd256: + case X86::BI__builtin_ia32_vpermil2ps: + case X86::BI__builtin_ia32_vpermil2ps256: i = 3, l = 0; u = 3; break; + case X86::BI__builtin_ia32_cmpb128_mask: + case X86::BI__builtin_ia32_cmpw128_mask: + case X86::BI__builtin_ia32_cmpd128_mask: + case X86::BI__builtin_ia32_cmpq128_mask: + case X86::BI__builtin_ia32_cmpb256_mask: + case X86::BI__builtin_ia32_cmpw256_mask: + case X86::BI__builtin_ia32_cmpd256_mask: + case X86::BI__builtin_ia32_cmpq256_mask: + case X86::BI__builtin_ia32_cmpb512_mask: + case X86::BI__builtin_ia32_cmpw512_mask: + case X86::BI__builtin_ia32_cmpd512_mask: + case X86::BI__builtin_ia32_cmpq512_mask: + case X86::BI__builtin_ia32_ucmpb128_mask: + case X86::BI__builtin_ia32_ucmpw128_mask: + case X86::BI__builtin_ia32_ucmpd128_mask: + case X86::BI__builtin_ia32_ucmpq128_mask: + case X86::BI__builtin_ia32_ucmpb256_mask: + case X86::BI__builtin_ia32_ucmpw256_mask: + case X86::BI__builtin_ia32_ucmpd256_mask: + case X86::BI__builtin_ia32_ucmpq256_mask: + case X86::BI__builtin_ia32_ucmpb512_mask: + case X86::BI__builtin_ia32_ucmpw512_mask: + case X86::BI__builtin_ia32_ucmpd512_mask: + case X86::BI__builtin_ia32_ucmpq512_mask: i = 2; l = 0; u = 7; break; + case X86::BI__builtin_ia32_roundps: + case X86::BI__builtin_ia32_roundpd: + case X86::BI__builtin_ia32_roundps256: + case X86::BI__builtin_ia32_roundpd256: i = 1, l = 0; u = 15; break; + case X86::BI__builtin_ia32_roundss: + case X86::BI__builtin_ia32_roundsd: i = 2, l = 0; u = 15; break; case X86::BI__builtin_ia32_cmpps: case X86::BI__builtin_ia32_cmpss: case X86::BI__builtin_ia32_cmppd: - case X86::BI__builtin_ia32_cmpsd: i = 2; l = 0; u = 31; break; + case X86::BI__builtin_ia32_cmpsd: + case X86::BI__builtin_ia32_cmpps256: + case X86::BI__builtin_ia32_cmppd256: + case X86::BI__builtin_ia32_cmpps512_mask: + case X86::BI__builtin_ia32_cmppd512_mask: i = 2; l = 0; u = 31; break; + case X86::BI__builtin_ia32_vpcomub: + case X86::BI__builtin_ia32_vpcomuw: + case X86::BI__builtin_ia32_vpcomud: + case X86::BI__builtin_ia32_vpcomuq: + case X86::BI__builtin_ia32_vpcomb: + case X86::BI__builtin_ia32_vpcomw: + case X86::BI__builtin_ia32_vpcomd: + case X86::BI__builtin_ia32_vpcomq: i = 2; l = 0; u = 7; break; } return SemaBuiltinConstantArgRange(TheCall, i, l, u); } @@ -1119,11 +1334,14 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, const FunctionProtoType *Proto) { - const VarDecl *V = dyn_cast<VarDecl>(NDecl); - if (!V) + QualType Ty; + if (const auto *V = dyn_cast<VarDecl>(NDecl)) + Ty = V->getType(); + else if (const auto *F = dyn_cast<FieldDecl>(NDecl)) + Ty = F->getType(); + else return false; - QualType Ty = V->getType(); if (!Ty->isBlockPointerType() && !Ty->isFunctionPointerType()) return false; @@ -1220,9 +1438,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, // M is C if C is an integer, and ptrdiff_t if C is a pointer, and // the int parameters are for orderings. - assert(AtomicExpr::AO__c11_atomic_init == 0 && - AtomicExpr::AO__c11_atomic_fetch_xor + 1 == AtomicExpr::AO__atomic_load - && "need to update code for modified C11 atomics"); + static_assert(AtomicExpr::AO__c11_atomic_init == 0 && + AtomicExpr::AO__c11_atomic_fetch_xor + 1 == + AtomicExpr::AO__atomic_load, + "need to update code for modified C11 atomics"); bool IsC11 = Op >= AtomicExpr::AO__c11_atomic_init && Op <= AtomicExpr::AO__c11_atomic_fetch_xor; bool IsN = Op == AtomicExpr::AO__atomic_load_n || @@ -2039,7 +2258,7 @@ bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) { if (checkBuiltinArgument(*this, Call, 0)) return true; - static const struct { + const struct { unsigned ArgNo; QualType Type; } ArgumentTypes[] = { @@ -2286,7 +2505,7 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) { if (Arg->isInstantiationDependent()) return false; if (Arg->HasSideEffects(Context)) - return Diag(Arg->getLocStart(), diag::warn_assume_side_effects) + Diag(Arg->getLocStart(), diag::warn_assume_side_effects) << Arg->getSourceRange() << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier(); @@ -2604,6 +2823,7 @@ Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { .Case("strfmon", FST_Strfmon) .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf) .Case("freebsd_kprintf", FST_FreeBSDKPrintf) + .Case("os_trace", FST_OSTrace) .Default(FST_Unknown); } @@ -3074,10 +3294,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, if (InFunctionCall) { const Sema::SemaDiagnosticBuilder &D = S.Diag(Loc, PDiag); D << StringRange; - for (ArrayRef<FixItHint>::iterator I = FixIt.begin(), E = FixIt.end(); - I != E; ++I) { - D << *I; - } + D << FixIt; } else { S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag) << ArgumentExpr->getSourceRange(); @@ -3087,10 +3304,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, diag::note_format_string_defined); Note << StringRange; - for (ArrayRef<FixItHint>::iterator I = FixIt.begin(), E = FixIt.end(); - I != E; ++I) { - Note << *I; - } + Note << FixIt; } } @@ -3600,8 +3814,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, ExprTy = TET->getUnderlyingExpr()->getType(); } - if (AT.matchesType(S.Context, ExprTy)) + analyze_printf::ArgType::MatchKind match = AT.matchesType(S.Context, ExprTy); + + if (match == analyze_printf::ArgType::Match) { return true; + } // Look through argument promotions for our error message's reported type. // This includes the integral and floating promotions, but excludes array @@ -3696,16 +3913,18 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen); if (IntendedTy == ExprTy && !ShouldNotPrintDirectly) { + unsigned diag = diag::warn_format_conversion_argument_type_mismatch; + if (match == analyze_format_string::ArgType::NoMatchPedantic) { + diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; + } // In this case, the specifier is wrong and should be changed to match // the argument. - EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << IntendedTy << IsEnum - << E->getSourceRange(), - E->getLocStart(), - /*IsStringLocation*/false, - SpecRange, - FixItHint::CreateReplacement(SpecRange, os.str())); + EmitFormatDiagnostic(S.PDiag(diag) + << AT.getRepresentativeTypeName(S.Context) + << IntendedTy << IsEnum << E->getSourceRange(), + E->getLocStart(), + /*IsStringLocation*/ false, SpecRange, + FixItHint::CreateReplacement(SpecRange, os.str())); } else { // The canonical type for formatting this value is different from the @@ -3779,15 +3998,18 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // arguments here. switch (S.isValidVarArgType(ExprTy)) { case Sema::VAK_Valid: - case Sema::VAK_ValidInCXX11: + case Sema::VAK_ValidInCXX11: { + unsigned diag = diag::warn_format_conversion_argument_type_mismatch; + if (match == analyze_printf::ArgType::NoMatchPedantic) { + diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; + } + EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum - << CSR - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/false, CSR); + S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy + << IsEnum << CSR << E->getSourceRange(), + E->getLocStart(), /*IsStringLocation*/ false, CSR); break; - + } case Sema::VAK_Undefined: case Sema::VAK_MSVCUndefined: EmitFormatDiagnostic( @@ -3919,13 +4141,13 @@ bool CheckScanfHandler::HandleScanfSpecifier( FixItHint::CreateRemoval(R)); } } - + if (!FS.consumesDataArgument()) { // FIXME: Technically specifying a precision or field width here // makes no sense. Worth issuing a warning at some point. return true; } - + // Consume the argument. unsigned argIndex = FS.getArgIndex(); if (argIndex < NumDataArgs) { @@ -3934,7 +4156,7 @@ bool CheckScanfHandler::HandleScanfSpecifier( // function if we encounter some other error. CoveredArgs.set(argIndex); } - + // Check the length modifier is valid with the given conversion specifier. if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo())) HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen, @@ -3951,47 +4173,57 @@ bool CheckScanfHandler::HandleScanfSpecifier( // The remaining checks depend on the data arguments. if (HasVAListArg) return true; - + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) return false; - + // Check that the argument type matches the format specifier. const Expr *Ex = getDataArg(argIndex); if (!Ex) return true; const analyze_format_string::ArgType &AT = FS.getArgType(S.Context); - if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) { - ScanfSpecifier fixedFS = FS; - bool success = fixedFS.fixType(Ex->getType(), - Ex->IgnoreImpCasts()->getType(), - S.getLangOpts(), S.Context); - - if (success) { - // Get the fix string from the fixed format specifier. - SmallString<128> buf; - llvm::raw_svector_ostream os(buf); - fixedFS.toString(os); - EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false - << Ex->getSourceRange(), + if (!AT.isValid()) { + return true; + } + + analyze_format_string::ArgType::MatchKind match = + AT.matchesType(S.Context, Ex->getType()); + if (match == analyze_format_string::ArgType::Match) { + return true; + } + + ScanfSpecifier fixedFS = FS; + bool success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(), + S.getLangOpts(), S.Context); + + unsigned diag = diag::warn_format_conversion_argument_type_mismatch; + if (match == analyze_format_string::ArgType::NoMatchPedantic) { + diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; + } + + if (success) { + // Get the fix string from the fixed format specifier. + SmallString<128> buf; + llvm::raw_svector_ostream os(buf); + fixedFS.toString(os); + + EmitFormatDiagnostic( + S.PDiag(diag) << AT.getRepresentativeTypeName(S.Context) + << Ex->getType() << false << Ex->getSourceRange(), Ex->getLocStart(), - /*IsStringLocation*/false, + /*IsStringLocation*/ false, getSpecifierRange(startSpecifier, specifierLen), FixItHint::CreateReplacement( - getSpecifierRange(startSpecifier, specifierLen), - os.str())); - } else { - EmitFormatDiagnostic( - S.PDiag(diag::warn_format_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << Ex->getType() << false - << Ex->getSourceRange(), - Ex->getLocStart(), - /*IsStringLocation*/false, - getSpecifierRange(startSpecifier, specifierLen)); - } + getSpecifierRange(startSpecifier, specifierLen), os.str())); + } else { + EmitFormatDiagnostic(S.PDiag(diag) + << AT.getRepresentativeTypeName(S.Context) + << Ex->getType() << false << Ex->getSourceRange(), + Ex->getLocStart(), + /*IsStringLocation*/ false, + getSpecifierRange(startSpecifier, specifierLen)); } return true; @@ -4046,9 +4278,9 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, } if (Type == FST_Printf || Type == FST_NSString || - Type == FST_FreeBSDKPrintf) { + Type == FST_FreeBSDKPrintf || Type == FST_OSTrace) { CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, - numDataArgs, (Type == FST_NSString), + numDataArgs, (Type == FST_NSString || Type == FST_OSTrace), Str, HasVAListArg, Args, format_idx, inFunctionCall, CallType, CheckedVarArgs); @@ -4533,7 +4765,7 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T, /// \brief If E is a sizeof expression, returns its argument expression, /// otherwise returns NULL. -static const Expr *getSizeOfExprArg(const Expr* E) { +static const Expr *getSizeOfExprArg(const Expr *E) { if (const UnaryExprOrTypeTraitExpr *SizeOf = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType()) @@ -4543,7 +4775,7 @@ static const Expr *getSizeOfExprArg(const Expr* E) { } /// \brief If E is a sizeof expression, returns its argument type. -static QualType getSizeOfArgType(const Expr* E) { +static QualType getSizeOfArgType(const Expr *E) { if (const UnaryExprOrTypeTraitExpr *SizeOf = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) if (SizeOf->getKind() == clang::UETT_SizeOf) @@ -4589,8 +4821,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange(); QualType DestTy = Dest->getType(); + QualType PointeeTy; if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) { - QualType PointeeTy = DestPtrTy->getPointeeType(); + PointeeTy = DestPtrTy->getPointeeType(); // Never warn about void type pointers. This can be used to suppress // false positives. @@ -4670,47 +4903,53 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, break; } } + } else if (DestTy->isArrayType()) { + PointeeTy = DestTy; + } - // Always complain about dynamic classes. - bool IsContained; - if (const CXXRecordDecl *ContainedRD = - getContainedDynamicClass(PointeeTy, IsContained)) { - - unsigned OperationType = 0; - // "overwritten" if we're warning about the destination for any call - // but memcmp; otherwise a verb appropriate to the call. - if (ArgIdx != 0 || BId == Builtin::BImemcmp) { - if (BId == Builtin::BImemcpy) - OperationType = 1; - else if(BId == Builtin::BImemmove) - OperationType = 2; - else if (BId == Builtin::BImemcmp) - OperationType = 3; - } - - DiagRuntimeBehavior( - Dest->getExprLoc(), Dest, - PDiag(diag::warn_dyn_class_memaccess) - << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx) - << FnName << IsContained << ContainedRD << OperationType - << Call->getCallee()->getSourceRange()); - } else if (PointeeTy.hasNonTrivialObjCLifetime() && - BId != Builtin::BImemset) - DiagRuntimeBehavior( - Dest->getExprLoc(), Dest, - PDiag(diag::warn_arc_object_memaccess) - << ArgIdx << FnName << PointeeTy - << Call->getCallee()->getSourceRange()); - else - continue; + if (PointeeTy == QualType()) + continue; + // Always complain about dynamic classes. + bool IsContained; + if (const CXXRecordDecl *ContainedRD = + getContainedDynamicClass(PointeeTy, IsContained)) { + + unsigned OperationType = 0; + // "overwritten" if we're warning about the destination for any call + // but memcmp; otherwise a verb appropriate to the call. + if (ArgIdx != 0 || BId == Builtin::BImemcmp) { + if (BId == Builtin::BImemcpy) + OperationType = 1; + else if(BId == Builtin::BImemmove) + OperationType = 2; + else if (BId == Builtin::BImemcmp) + OperationType = 3; + } + DiagRuntimeBehavior( Dest->getExprLoc(), Dest, - PDiag(diag::note_bad_memaccess_silence) - << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); - break; - } + PDiag(diag::warn_dyn_class_memaccess) + << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx) + << FnName << IsContained << ContainedRD << OperationType + << Call->getCallee()->getSourceRange()); + } else if (PointeeTy.hasNonTrivialObjCLifetime() && + BId != Builtin::BImemset) + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::warn_arc_object_memaccess) + << ArgIdx << FnName << PointeeTy + << Call->getCallee()->getSourceRange()); + else + continue; + + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::note_bad_memaccess_silence) + << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); + break; } + } // A little helper routine: ignore addition and subtraction of integer literals. @@ -5861,7 +6100,7 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, // TODO: Investigate using GetExprRange() to get tighter bounds // on the bit ranges. QualType OtherT = Other->getType(); - if (const AtomicType *AT = dyn_cast<AtomicType>(OtherT)) + if (const auto *AT = OtherT->getAs<AtomicType>()) OtherT = AT->getValueType(); IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); unsigned OtherWidth = OtherRange.Width; @@ -6705,8 +6944,11 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { E = POE->getResultExpr(); } - if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) - return AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) { + if (OVE->getSourceExpr()) + AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); + return; + } // Skip past explicit casts. if (isa<ExplicitCastExpr>(E)) { @@ -6788,7 +7030,7 @@ static bool CheckForReference(Sema &SemaRef, const Expr *E, if (!M->getMemberDecl()->getType()->isReferenceType()) return false; } else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) { - if (!Call->getCallReturnType()->isReferenceType()) + if (!Call->getCallReturnType(SemaRef.Context)->isReferenceType()) return false; FD = Call->getDirectCallee(); } else { @@ -7533,6 +7775,35 @@ void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc); } +static void diagnoseArrayStarInParamType(Sema &S, QualType PType, + SourceLocation Loc) { + if (!PType->isVariablyModifiedType()) + return; + if (const auto *PointerTy = dyn_cast<PointerType>(PType)) { + diagnoseArrayStarInParamType(S, PointerTy->getPointeeType(), Loc); + return; + } + if (const auto *ReferenceTy = dyn_cast<ReferenceType>(PType)) { + diagnoseArrayStarInParamType(S, ReferenceTy->getPointeeType(), Loc); + return; + } + if (const auto *ParenTy = dyn_cast<ParenType>(PType)) { + diagnoseArrayStarInParamType(S, ParenTy->getInnerType(), Loc); + return; + } + + const ArrayType *AT = S.Context.getAsArrayType(PType); + if (!AT) + return; + + if (AT->getSizeModifier() != ArrayType::Star) { + diagnoseArrayStarInParamType(S, AT->getElementType(), Loc); + return; + } + + S.Diag(Loc, diag::err_array_star_in_function_definition); +} + /// CheckParmsForFunctionDef - Check that the parameters of the given /// function are appropriate for the definition of a function. This /// takes care of any checks that cannot be performed on the @@ -7571,15 +7842,9 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, // notation in their sequences of declarator specifiers to specify // variable length array types. QualType PType = Param->getOriginalType(); - while (const ArrayType *AT = Context.getAsArrayType(PType)) { - if (AT->getSizeModifier() == ArrayType::Star) { - // FIXME: This diagnostic should point the '[*]' if source-location - // information is added for it. - Diag(Param->getLocation(), diag::err_array_star_in_function_definition); - break; - } - PType= AT->getElementType(); - } + // FIXME: This diagnostic should point the '[*]' if source-location + // information is added for it. + diagnoseArrayStarInParamType(*this, PType, Param->getLocation()); // MSVC destroys objects passed by value in the callee. Therefore a // function definition which takes such a parameter must be able to call the @@ -8097,6 +8362,236 @@ static bool isSetterLikeSelector(Selector sel) { return !isLowercase(str.front()); } +static Optional<int> GetNSMutableArrayArgumentIndex(Sema &S, + ObjCMessageExpr *Message) { + if (S.NSMutableArrayPointer.isNull()) { + IdentifierInfo *NSMutableArrayId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableArray); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableArrayId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + ObjCInterfaceDecl *InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (!InterfaceDecl) { + return None; + } + QualType NSMutableArrayObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSMutableArrayPointer = + S.Context.getObjCObjectPointerType(NSMutableArrayObject); + } + + if (S.NSMutableArrayPointer != Message->getReceiverType()) { + return None; + } + + Selector Sel = Message->getSelector(); + + Optional<NSAPI::NSArrayMethodKind> MKOpt = + S.NSAPIObj->getNSArrayMethodKind(Sel); + if (!MKOpt) { + return None; + } + + NSAPI::NSArrayMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableArr_addObject: + case NSAPI::NSMutableArr_insertObjectAtIndex: + case NSAPI::NSMutableArr_setObjectAtIndexedSubscript: + return 0; + case NSAPI::NSMutableArr_replaceObjectAtIndex: + return 1; + + default: + return None; + } + + return None; +} + +static +Optional<int> GetNSMutableDictionaryArgumentIndex(Sema &S, + ObjCMessageExpr *Message) { + + if (S.NSMutableDictionaryPointer.isNull()) { + IdentifierInfo *NSMutableDictionaryId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableDictionary); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableDictionaryId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + ObjCInterfaceDecl *InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (!InterfaceDecl) { + return None; + } + QualType NSMutableDictionaryObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSMutableDictionaryPointer = + S.Context.getObjCObjectPointerType(NSMutableDictionaryObject); + } + + if (S.NSMutableDictionaryPointer != Message->getReceiverType()) { + return None; + } + + Selector Sel = Message->getSelector(); + + Optional<NSAPI::NSDictionaryMethodKind> MKOpt = + S.NSAPIObj->getNSDictionaryMethodKind(Sel); + if (!MKOpt) { + return None; + } + + NSAPI::NSDictionaryMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableDict_setObjectForKey: + case NSAPI::NSMutableDict_setValueForKey: + case NSAPI::NSMutableDict_setObjectForKeyedSubscript: + return 0; + + default: + return None; + } + + return None; +} + +static Optional<int> GetNSSetArgumentIndex(Sema &S, ObjCMessageExpr *Message) { + + ObjCInterfaceDecl *InterfaceDecl; + if (S.NSMutableSetPointer.isNull()) { + IdentifierInfo *NSMutableSetId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableSet); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableSetId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (InterfaceDecl) { + QualType NSMutableSetObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSMutableSetPointer = + S.Context.getObjCObjectPointerType(NSMutableSetObject); + } + } + + if (S.NSCountedSetPointer.isNull()) { + IdentifierInfo *NSCountedSetId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSCountedSet); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSCountedSetId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (InterfaceDecl) { + QualType NSCountedSetObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSCountedSetPointer = + S.Context.getObjCObjectPointerType(NSCountedSetObject); + } + } + + if (S.NSMutableOrderedSetPointer.isNull()) { + IdentifierInfo *NSOrderedSetId = + S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableOrderedSet); + NamedDecl *IF = S.LookupSingleName(S.TUScope, NSOrderedSetId, + Message->getLocStart(), + Sema::LookupOrdinaryName); + InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (InterfaceDecl) { + QualType NSOrderedSetObject = + S.Context.getObjCInterfaceType(InterfaceDecl); + S.NSMutableOrderedSetPointer = + S.Context.getObjCObjectPointerType(NSOrderedSetObject); + } + } + + QualType ReceiverType = Message->getReceiverType(); + + bool IsMutableSet = !S.NSMutableSetPointer.isNull() && + ReceiverType == S.NSMutableSetPointer; + bool IsMutableOrderedSet = !S.NSMutableOrderedSetPointer.isNull() && + ReceiverType == S.NSMutableOrderedSetPointer; + bool IsCountedSet = !S.NSCountedSetPointer.isNull() && + ReceiverType == S.NSCountedSetPointer; + + if (!IsMutableSet && !IsMutableOrderedSet && !IsCountedSet) { + return None; + } + + Selector Sel = Message->getSelector(); + + Optional<NSAPI::NSSetMethodKind> MKOpt = S.NSAPIObj->getNSSetMethodKind(Sel); + if (!MKOpt) { + return None; + } + + NSAPI::NSSetMethodKind MK = *MKOpt; + + switch (MK) { + case NSAPI::NSMutableSet_addObject: + case NSAPI::NSOrderedSet_setObjectAtIndex: + case NSAPI::NSOrderedSet_setObjectAtIndexedSubscript: + case NSAPI::NSOrderedSet_insertObjectAtIndex: + return 0; + case NSAPI::NSOrderedSet_replaceObjectAtIndexWithObject: + return 1; + } + + return None; +} + +void Sema::CheckObjCCircularContainer(ObjCMessageExpr *Message) { + if (!Message->isInstanceMessage()) { + return; + } + + Optional<int> ArgOpt; + + if (!(ArgOpt = GetNSMutableArrayArgumentIndex(*this, Message)) && + !(ArgOpt = GetNSMutableDictionaryArgumentIndex(*this, Message)) && + !(ArgOpt = GetNSSetArgumentIndex(*this, Message))) { + return; + } + + int ArgIndex = *ArgOpt; + + Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts(); + if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) { + Receiver = OE->getSourceExpr()->IgnoreImpCasts(); + } + + Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts(); + if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) { + Arg = OE->getSourceExpr()->IgnoreImpCasts(); + } + + if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) { + if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) { + if (ReceiverRE->getDecl() == ArgRE->getDecl()) { + ValueDecl *Decl = ReceiverRE->getDecl(); + Diag(Message->getSourceRange().getBegin(), + diag::warn_objc_circular_container) + << Decl->getName(); + Diag(Decl->getLocation(), + diag::note_objc_circular_container_declared_here) + << Decl->getName(); + } + } + } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) { + if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) { + if (IvarRE->getDecl() == IvarArgRE->getDecl()) { + ObjCIvarDecl *Decl = IvarRE->getDecl(); + Diag(Message->getSourceRange().getBegin(), + diag::warn_objc_circular_container) + << Decl->getName(); + Diag(Decl->getLocation(), + diag::note_objc_circular_container_declared_here) + << Decl->getName(); + } + } + } + +} + /// Check a message send to see if it's likely to cause a retain cycle. void Sema::checkRetainCycles(ObjCMessageExpr *msg) { // Only check instance methods whose selector looks like a setter. @@ -8281,7 +8776,7 @@ bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, // Get line numbers of statement and body. bool StmtLineInvalid; - unsigned StmtLine = SourceMgr.getSpellingLineNumber(StmtLoc, + unsigned StmtLine = SourceMgr.getPresumedLineNumber(StmtLoc, &StmtLineInvalid); if (StmtLineInvalid) return false; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index 48bdd2a..18d352b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -495,7 +495,6 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, AsNestedNameSpecifier = false; ND = ND->getUnderlyingDecl(); - unsigned IDNS = ND->getIdentifierNamespace(); // Skip unnamed entities. if (!ND->getDeclName()) @@ -503,7 +502,7 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, // Friend declarations and declarations introduced due to friends are never // added as results. - if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)) + if (ND->getFriendObjectKind() == Decl::FOK_Undeclared) return false; // Class template (partial) specializations are never added as results. @@ -800,8 +799,8 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) { DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(RecordTy)); - DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName); - for (DeclContext::lookup_const_iterator I = Ctors.begin(), + DeclContext::lookup_result Ctors = Record->lookup(ConstructorName); + for (DeclContext::lookup_iterator I = Ctors.begin(), E = Ctors.end(); I != E; ++I) { R.Declaration = *I; @@ -2018,7 +2017,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, if (SemaRef.getLangOpts().C11) { // _Alignof Builder.AddResultTypeChunk("size_t"); - if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition()) + if (SemaRef.PP.isMacroDefined("alignof")) Builder.AddTypedTextChunk("alignof"); else Builder.AddTypedTextChunk("_Alignof"); @@ -2086,15 +2085,14 @@ static void AddResultTypeChunk(ASTContext &Context, Result.getAllocator())); } -static void MaybeAddSentinel(ASTContext &Context, +static void MaybeAddSentinel(Preprocessor &PP, const NamedDecl *FunctionOrMethod, CodeCompletionBuilder &Result) { if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) if (Sentinel->getSentinel() == 0) { - if (Context.getLangOpts().ObjC1 && - Context.Idents.get("nil").hasMacroDefinition()) + if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil")) Result.AddTextChunk(", nil"); - else if (Context.Idents.get("NULL").hasMacroDefinition()) + else if (PP.isMacroDefined("NULL")) Result.AddTextChunk(", NULL"); else Result.AddTextChunk(", (void*)0"); @@ -2118,8 +2116,7 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals) { return Result; } -static std::string FormatFunctionParameter(ASTContext &Context, - const PrintingPolicy &Policy, +static std::string FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param, bool SuppressName = false, bool SuppressBlock = false) { @@ -2218,7 +2215,7 @@ static std::string FormatFunctionParameter(ASTContext &Context, for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) { if (I) Params += ", "; - Params += FormatFunctionParameter(Context, Policy, Block.getParam(I), + Params += FormatFunctionParameter(Policy, Block.getParam(I), /*SuppressName=*/false, /*SuppressBlock=*/true); @@ -2248,7 +2245,7 @@ static std::string FormatFunctionParameter(ASTContext &Context, } /// \brief Add function parameter chunks to the given code completion string. -static void AddFunctionParameterChunks(ASTContext &Context, +static void AddFunctionParameterChunks(Preprocessor &PP, const PrintingPolicy &Policy, const FunctionDecl *Function, CodeCompletionBuilder &Result, @@ -2266,7 +2263,7 @@ static void AddFunctionParameterChunks(ASTContext &Context, Result.getCodeCompletionTUInfo()); if (!FirstParameter) Opt.AddChunk(CodeCompletionString::CK_Comma); - AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true); + AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true); Result.AddOptionalChunk(Opt.TakeString()); break; } @@ -2279,9 +2276,8 @@ static void AddFunctionParameterChunks(ASTContext &Context, InOptional = false; // Format the placeholder string. - std::string PlaceholderStr = FormatFunctionParameter(Context, Policy, - Param); - + std::string PlaceholderStr = FormatFunctionParameter(Policy, Param); + if (Function->isVariadic() && P == N - 1) PlaceholderStr += ", ..."; @@ -2296,7 +2292,7 @@ static void AddFunctionParameterChunks(ASTContext &Context, if (Proto->getNumParams() == 0) Result.AddPlaceholderChunk("..."); - MaybeAddSentinel(Context, Function, Result); + MaybeAddSentinel(PP, Function, Result); } } @@ -2309,7 +2305,11 @@ static void AddTemplateParameterChunks(ASTContext &Context, unsigned Start = 0, bool InDefaultArg = false) { bool FirstParameter = true; - + + // Prefer to take the template parameter names from the first declaration of + // the template. + Template = cast<TemplateDecl>(Template->getCanonicalDecl()); + TemplateParameterList *Params = Template->getTemplateParameters(); TemplateParameterList::iterator PEnd = Params->end(); if (MaxParameters) @@ -2572,11 +2572,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, } if (Kind == RK_Macro) { - const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro); - assert(MD && "Not a macro?"); - const MacroInfo *MI = MD->getMacroInfo(); - assert((!MD->isDefined() || MI) && "missing MacroInfo for define"); - + const MacroInfo *MI = PP.getMacroInfo(Macro); Result.AddTypedTextChunk( Result.getAllocator().CopyString(Macro->getName())); @@ -2651,7 +2647,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Ctx, Policy); AddTypedNameChunk(Ctx, Policy, ND, Result); Result.AddChunk(CodeCompletionString::CK_LeftParen); - AddFunctionParameterChunks(Ctx, Policy, Function, Result); + AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); return Result.TakeString(); @@ -2705,7 +2701,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, // Add the function parameters Result.AddChunk(CodeCompletionString::CK_LeftParen); - AddFunctionParameterChunks(Ctx, Policy, Function, Result); + AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); return Result.TakeString(); @@ -2766,7 +2762,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, std::string Arg; if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity) - Arg = FormatFunctionParameter(Ctx, Policy, *P, true); + Arg = FormatFunctionParameter(Policy, *P, true); else { (*P)->getType().getAsStringInternal(Arg, Policy); Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier()) @@ -2797,7 +2793,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Result.AddPlaceholderChunk(", ..."); } - MaybeAddSentinel(Ctx, Method, Result); + MaybeAddSentinel(PP, Method, Result); } return Result.TakeString(); @@ -2812,73 +2808,115 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } +/// \brief Add function overload parameter chunks to the given code completion +/// string. +static void AddOverloadParameterChunks(ASTContext &Context, + const PrintingPolicy &Policy, + const FunctionDecl *Function, + const FunctionProtoType *Prototype, + CodeCompletionBuilder &Result, + unsigned CurrentArg, + unsigned Start = 0, + bool InOptional = false) { + bool FirstParameter = true; + unsigned NumParams = Function ? Function->getNumParams() + : Prototype->getNumParams(); + + for (unsigned P = Start; P != NumParams; ++P) { + if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) { + // When we see an optional default argument, put that argument and + // the remaining default arguments into a new, optional string. + CodeCompletionBuilder Opt(Result.getAllocator(), + Result.getCodeCompletionTUInfo()); + if (!FirstParameter) + Opt.AddChunk(CodeCompletionString::CK_Comma); + // Optional sections are nested. + AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt, + CurrentArg, P, /*InOptional=*/true); + Result.AddOptionalChunk(Opt.TakeString()); + return; + } + + if (FirstParameter) + FirstParameter = false; + else + Result.AddChunk(CodeCompletionString::CK_Comma); + + InOptional = false; + + // Format the placeholder string. + std::string Placeholder; + if (Function) + Placeholder = FormatFunctionParameter(Policy, Function->getParamDecl(P)); + else + Placeholder = Prototype->getParamType(P).getAsString(Policy); + + if (P == CurrentArg) + Result.AddCurrentParameterChunk( + Result.getAllocator().CopyString(Placeholder)); + else + Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder)); + } + + if (Prototype && Prototype->isVariadic()) { + CodeCompletionBuilder Opt(Result.getAllocator(), + Result.getCodeCompletionTUInfo()); + if (!FirstParameter) + Opt.AddChunk(CodeCompletionString::CK_Comma); + + if (CurrentArg < NumParams) + Opt.AddPlaceholderChunk("..."); + else + Opt.AddCurrentParameterChunk("..."); + + Result.AddOptionalChunk(Opt.TakeString()); + } +} + CodeCompletionString * CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( - unsigned CurrentArg, - Sema &S, - CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo) const { + unsigned CurrentArg, Sema &S, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + bool IncludeBriefComments) const { PrintingPolicy Policy = getCompletionPrintingPolicy(S); // FIXME: Set priority, availability appropriately. CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available); FunctionDecl *FDecl = getFunction(); - AddResultTypeChunk(S.Context, Policy, FDecl, Result); - const FunctionProtoType *Proto + const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(getFunctionType()); if (!FDecl && !Proto) { // Function without a prototype. Just give the return type and a // highlighted ellipsis. const FunctionType *FT = getFunctionType(); - Result.AddTextChunk(GetCompletionTypeString(FT->getReturnType(), S.Context, - Policy, Result.getAllocator())); + Result.AddResultTypeChunk(Result.getAllocator().CopyString( + FT->getReturnType().getAsString(Policy))); Result.AddChunk(CodeCompletionString::CK_LeftParen); Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); Result.AddChunk(CodeCompletionString::CK_RightParen); return Result.TakeString(); } - - if (FDecl) + + if (FDecl) { + if (IncludeBriefComments && CurrentArg < FDecl->getNumParams()) + if (auto RC = S.getASTContext().getRawCommentForAnyRedecl( + FDecl->getParamDecl(CurrentArg))) + Result.addBriefComment(RC->getBriefText(S.getASTContext())); + AddResultTypeChunk(S.Context, Policy, FDecl, Result); Result.AddTextChunk( - Result.getAllocator().CopyString(FDecl->getNameAsString())); - else - Result.AddTextChunk(Result.getAllocator().CopyString( + Result.getAllocator().CopyString(FDecl->getNameAsString())); + } else { + Result.AddResultTypeChunk( + Result.getAllocator().CopyString( Proto->getReturnType().getAsString(Policy))); + } Result.AddChunk(CodeCompletionString::CK_LeftParen); - unsigned NumParams = FDecl ? FDecl->getNumParams() : Proto->getNumParams(); - for (unsigned I = 0; I != NumParams; ++I) { - if (I) - Result.AddChunk(CodeCompletionString::CK_Comma); - - std::string ArgString; - QualType ArgType; - - if (FDecl) { - ArgString = FDecl->getParamDecl(I)->getNameAsString(); - ArgType = FDecl->getParamDecl(I)->getOriginalType(); - } else { - ArgType = Proto->getParamType(I); - } - - ArgType.getAsStringInternal(ArgString, Policy); - - if (I == CurrentArg) - Result.AddChunk(CodeCompletionString::CK_CurrentParameter, - Result.getAllocator().CopyString(ArgString)); - else - Result.AddTextChunk(Result.getAllocator().CopyString(ArgString)); - } - - if (Proto && Proto->isVariadic()) { - Result.AddChunk(CodeCompletionString::CK_Comma); - if (CurrentArg < NumParams) - Result.AddTextChunk("..."); - else - Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); - } + AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result, + CurrentArg); Result.AddChunk(CodeCompletionString::CK_RightParen); - + return Result.TakeString(); } @@ -2990,8 +3028,9 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); M != MEnd; ++M) { - if (IncludeUndefined || M->first->hasMacroDefinition()) { - if (MacroInfo *MI = M->second->getMacroInfo()) + auto MD = PP.getMacroDefinition(M->first); + if (IncludeUndefined || MD) { + if (MacroInfo *MI = MD.getMacroInfo()) if (MI->isUsedForHeaderGuard()) continue; @@ -3816,7 +3855,74 @@ static bool anyNullArguments(ArrayRef<Expr *> Args) { return false; } -void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { +typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; + +static void mergeCandidatesWithResults(Sema &SemaRef, + SmallVectorImpl<ResultCandidate> &Results, + OverloadCandidateSet &CandidateSet, + SourceLocation Loc) { + if (!CandidateSet.empty()) { + // Sort the overload candidate set by placing the best overloads first. + std::stable_sort( + CandidateSet.begin(), CandidateSet.end(), + [&](const OverloadCandidate &X, const OverloadCandidate &Y) { + return isBetterOverloadCandidate(SemaRef, X, Y, Loc); + }); + + // Add the remaining viable overload candidates as code-completion results. + for (auto &Candidate : CandidateSet) + if (Candidate.Viable) + Results.push_back(ResultCandidate(Candidate.Function)); + } +} + +/// \brief Get the type of the Nth parameter from a given set of overload +/// candidates. +static QualType getParamType(Sema &SemaRef, + ArrayRef<ResultCandidate> Candidates, + unsigned N) { + + // Given the overloads 'Candidates' for a function call matching all arguments + // up to N, return the type of the Nth parameter if it is the same for all + // overload candidates. + QualType ParamType; + for (auto &Candidate : Candidates) { + if (auto FType = Candidate.getFunctionType()) + if (auto Proto = dyn_cast<FunctionProtoType>(FType)) + if (N < Proto->getNumParams()) { + if (ParamType.isNull()) + ParamType = Proto->getParamType(N); + else if (!SemaRef.Context.hasSameUnqualifiedType( + ParamType.getNonReferenceType(), + Proto->getParamType(N).getNonReferenceType())) + // Otherwise return a default-constructed QualType. + return QualType(); + } + } + + return ParamType; +} + +static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S, + MutableArrayRef<ResultCandidate> Candidates, + unsigned CurrentArg, + bool CompleteExpressionWithCurrentArg = true) { + QualType ParamType; + if (CompleteExpressionWithCurrentArg) + ParamType = getParamType(SemaRef, Candidates, CurrentArg); + + if (ParamType.isNull()) + SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression); + else + SemaRef.CodeCompleteExpression(S, ParamType); + + if (!Candidates.empty()) + SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg, + Candidates.data(), + Candidates.size()); +} + +void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { if (!CodeCompleter) return; @@ -3825,7 +3931,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { // results. We may want to revisit this strategy in the future, // e.g., by merging the two kinds of results. - Expr *Fn = (Expr *)FnIn; + // FIXME: Provide support for variadic template functions. // Ignore type-dependent call expressions entirely. if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || @@ -3838,92 +3944,120 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { SourceLocation Loc = Fn->getExprLoc(); OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - // FIXME: What if we're calling something that isn't a function declaration? - // FIXME: What if we're calling a pseudo-destructor? - // FIXME: What if we're calling a member function? - - typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; SmallVector<ResultCandidate, 8> Results; Expr *NakedFn = Fn->IgnoreParenCasts(); - if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) + if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) AddOverloadedCallCandidates(ULE, Args, CandidateSet, - /*PartialOverloading=*/ true); - else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) { - FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); - if (FDecl) { - if (!getLangOpts().CPlusPlus || - !FDecl->getType()->getAs<FunctionProtoType>()) - Results.push_back(ResultCandidate(FDecl)); + /*PartialOverloading=*/true); + else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr; + if (UME->hasExplicitTemplateArgs()) { + UME->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + SmallVector<Expr *, 12> ArgExprs(1, UME->getBase()); + ArgExprs.append(Args.begin(), Args.end()); + UnresolvedSet<8> Decls; + Decls.append(UME->decls_begin(), UME->decls_end()); + AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } else { + FunctionDecl *FD = nullptr; + if (auto MCE = dyn_cast<MemberExpr>(NakedFn)) + FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl()); + else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn)) + FD = dyn_cast<FunctionDecl>(DRE->getDecl()); + if (FD) { // We check whether it's a resolved function declaration. + if (!getLangOpts().CPlusPlus || + !FD->getType()->getAs<FunctionProtoType>()) + Results.push_back(ResultCandidate(FD)); else - // FIXME: access? - AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args, - CandidateSet, false, /*PartialOverloading*/true); + AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + + } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) { + // If expression's type is CXXRecordDecl, it may overload the function + // call operator, so we check if it does and add them as candidates. + // A complete type is needed to lookup for member function call operators. + if (!RequireCompleteType(Loc, NakedFn->getType(), 0)) { + DeclarationName OpName = Context.DeclarationNames + .getCXXOperatorName(OO_Call); + LookupResult R(*this, OpName, Loc, LookupOrdinaryName); + LookupQualifiedName(R, DC); + R.suppressDiagnostics(); + SmallVector<Expr *, 12> ArgExprs(1, NakedFn); + ArgExprs.append(Args.begin(), Args.end()); + AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, + /*ExplicitArgs=*/nullptr, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } + } else { + // Lastly we check whether expression's type is function pointer or + // function. + QualType T = NakedFn->getType(); + if (!T->getPointeeType().isNull()) + T = T->getPointeeType(); + + if (auto FP = T->getAs<FunctionProtoType>()) { + if (!TooManyArguments(FP->getNumParams(), Args.size(), + /*PartialOverloading=*/true) || + FP->isVariadic()) + Results.push_back(ResultCandidate(FP)); + } else if (auto FT = T->getAs<FunctionType>()) + // No prototype and declaration, it may be a K & R style function. + Results.push_back(ResultCandidate(FT)); } } - - QualType ParamType; - - if (!CandidateSet.empty()) { - // Sort the overload candidate set by placing the best overloads first. - std::stable_sort( - CandidateSet.begin(), CandidateSet.end(), - [&](const OverloadCandidate &X, const OverloadCandidate &Y) { - return isBetterOverloadCandidate(*this, X, Y, Loc); - }); - // Add the remaining viable overload candidates as code-completion reslults. - for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), - CandEnd = CandidateSet.end(); - Cand != CandEnd; ++Cand) { - if (Cand->Viable) - Results.push_back(ResultCandidate(Cand->Function)); - } - - // From the viable candidates, try to determine the type of this parameter. - for (unsigned I = 0, N = Results.size(); I != N; ++I) { - if (const FunctionType *FType = Results[I].getFunctionType()) - if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType)) - if (Args.size() < Proto->getNumParams()) { - if (ParamType.isNull()) - ParamType = Proto->getParamType(Args.size()); - else if (!Context.hasSameUnqualifiedType( - ParamType.getNonReferenceType(), - Proto->getParamType(Args.size()) - .getNonReferenceType())) { - ParamType = QualType(); - break; - } - } - } - } else { - // Try to determine the parameter type from the type of the expression - // being called. - QualType FunctionType = Fn->getType(); - if (const PointerType *Ptr = FunctionType->getAs<PointerType>()) - FunctionType = Ptr->getPointeeType(); - else if (const BlockPointerType *BlockPtr - = FunctionType->getAs<BlockPointerType>()) - FunctionType = BlockPtr->getPointeeType(); - else if (const MemberPointerType *MemPtr - = FunctionType->getAs<MemberPointerType>()) - FunctionType = MemPtr->getPointeeType(); - - if (const FunctionProtoType *Proto - = FunctionType->getAs<FunctionProtoType>()) { - if (Args.size() < Proto->getNumParams()) - ParamType = Proto->getParamType(Args.size()); + mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); + CodeCompleteOverloadResults(*this, S, Results, Args.size(), + !CandidateSet.empty()); +} + +void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, + ArrayRef<Expr *> Args) { + if (!CodeCompleter) + return; + + // A complete type is needed to lookup for constructors. + if (RequireCompleteType(Loc, Type, 0)) + return; + + CXXRecordDecl *RD = Type->getAsCXXRecordDecl(); + if (!RD) { + CodeCompleteExpression(S, Type); + return; + } + + // FIXME: Provide support for member initializers. + // FIXME: Provide support for variadic template constructors. + + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); + + for (auto C : LookupConstructors(RD)) { + if (auto FD = dyn_cast<FunctionDecl>(C)) { + AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) { + AddTemplateOverloadCandidate(FTD, + DeclAccessPair::make(FTD, C->getAccess()), + /*ExplicitTemplateArgs=*/nullptr, + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); } } - if (ParamType.isNull()) - CodeCompleteOrdinaryName(S, PCC_Expression); - else - CodeCompleteExpression(S, ParamType); - - if (!Results.empty()) - CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(), - Results.size()); + SmallVector<ResultCandidate, 8> Results; + mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); + CodeCompleteOverloadResults(*this, S, Results, Args.size()); } void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { @@ -4981,7 +5115,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, // an action, e.g., // IBAction)<#selector#>:(id)sender if (DS.getObjCDeclQualifier() == 0 && !IsParameter && - Context.Idents.get("IBAction").hasMacroDefinition()) { + PP.isMacroDefined("IBAction")) { CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo(), CCP_CodePattern, CXAvailability_Available); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index c6af2ed..89f4b3a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -128,45 +128,85 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { return false; } +namespace { +enum class UnqualifiedTypeNameLookupResult { + NotFound, + FoundNonType, + FoundType +}; +} // namespace + +/// \brief Tries to perform unqualified lookup of the type decls in bases for +/// dependent class. +/// \return \a NotFound if no any decls is found, \a FoundNotType if found not a +/// type decl, \a FoundType if only type decls are found. +static UnqualifiedTypeNameLookupResult +lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II, + SourceLocation NameLoc, + const CXXRecordDecl *RD) { + if (!RD->hasDefinition()) + return UnqualifiedTypeNameLookupResult::NotFound; + // Look for type decls in base classes. + UnqualifiedTypeNameLookupResult FoundTypeDecl = + UnqualifiedTypeNameLookupResult::NotFound; + for (const auto &Base : RD->bases()) { + const CXXRecordDecl *BaseRD = nullptr; + if (auto *BaseTT = Base.getType()->getAs<TagType>()) + BaseRD = BaseTT->getAsCXXRecordDecl(); + else if (auto *TST = Base.getType()->getAs<TemplateSpecializationType>()) { + // Look for type decls in dependent base classes that have known primary + // templates. + if (!TST || !TST->isDependentType()) + continue; + auto *TD = TST->getTemplateName().getAsTemplateDecl(); + if (!TD) + continue; + auto *BasePrimaryTemplate = + dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl()); + if (!BasePrimaryTemplate) + continue; + BaseRD = BasePrimaryTemplate; + } + if (BaseRD) { + for (NamedDecl *ND : BaseRD->lookup(&II)) { + if (!isa<TypeDecl>(ND)) + return UnqualifiedTypeNameLookupResult::FoundNonType; + FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType; + } + if (FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound) { + switch (lookupUnqualifiedTypeNameInBase(S, II, NameLoc, BaseRD)) { + case UnqualifiedTypeNameLookupResult::FoundNonType: + return UnqualifiedTypeNameLookupResult::FoundNonType; + case UnqualifiedTypeNameLookupResult::FoundType: + FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType; + break; + case UnqualifiedTypeNameLookupResult::NotFound: + break; + } + } + } + } + + return FoundTypeDecl; +} + static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, const IdentifierInfo &II, SourceLocation NameLoc) { - // Find the first parent class template context, if any. - // FIXME: Perform the lookup in all enclosing class templates. + // Lookup in the parent class template context, if any. const CXXRecordDecl *RD = nullptr; - for (DeclContext *DC = S.CurContext; DC; DC = DC->getParent()) { + UnqualifiedTypeNameLookupResult FoundTypeDecl = + UnqualifiedTypeNameLookupResult::NotFound; + for (DeclContext *DC = S.CurContext; + DC && FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound; + DC = DC->getParent()) { + // Look for type decls in dependent base classes that have known primary + // templates. RD = dyn_cast<CXXRecordDecl>(DC); if (RD && RD->getDescribedClassTemplate()) - break; + FoundTypeDecl = lookupUnqualifiedTypeNameInBase(S, II, NameLoc, RD); } - if (!RD) - return ParsedType(); - - // Look for type decls in dependent base classes that have known primary - // templates. - bool FoundTypeDecl = false; - for (const auto &Base : RD->bases()) { - auto *TST = Base.getType()->getAs<TemplateSpecializationType>(); - if (!TST || !TST->isDependentType()) - continue; - auto *TD = TST->getTemplateName().getAsTemplateDecl(); - if (!TD) - continue; - auto *BasePrimaryTemplate = - dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl()); - if (!BasePrimaryTemplate) - continue; - // FIXME: Allow lookup into non-dependent bases of dependent bases, possibly - // by calling or integrating with the main LookupQualifiedName mechanism. - for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) { - if (FoundTypeDecl) - return ParsedType(); - FoundTypeDecl = isa<TypeDecl>(ND); - if (!FoundTypeDecl) - return ParsedType(); - } - } - if (!FoundTypeDecl) + if (FoundTypeDecl != UnqualifiedTypeNameLookupResult::FoundType) return ParsedType(); // We found some types in dependent base classes. Recover as if the user @@ -1708,7 +1748,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Loc, Loc, II, R, /*TInfo=*/nullptr, SC_Extern, false, - /*hasPrototype=*/true); + R->isFunctionProtoType()); New->setImplicit(); // Create Decl objects for each parameter, adding them to the @@ -1744,11 +1784,11 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, /// should not consider because they are not permitted to conflict, e.g., /// because they come from hidden sub-modules and do not refer to the same /// entity. -static void filterNonConflictingPreviousDecls(ASTContext &context, +static void filterNonConflictingPreviousDecls(Sema &S, NamedDecl *decl, LookupResult &previous){ // This is only interesting when modules are enabled. - if (!context.getLangOpts().Modules) + if (!S.getLangOpts().Modules) return; // Empty sets are uninteresting. @@ -1760,7 +1800,7 @@ static void filterNonConflictingPreviousDecls(ASTContext &context, NamedDecl *old = filter.next(); // Non-hidden declarations are never ignored. - if (!old->isHidden()) + if (S.isVisible(old)) continue; if (!old->isExternallyVisible()) @@ -1774,11 +1814,11 @@ static void filterNonConflictingPreviousDecls(ASTContext &context, /// entity if their types are the same. /// FIXME: This is notionally doing the same thing as ASTReaderDecl's /// isSameEntity. -static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context, +static void filterNonConflictingPreviousTypedefDecls(Sema &S, TypedefNameDecl *Decl, LookupResult &Previous) { // This is only interesting when modules are enabled. - if (!Context.getLangOpts().Modules) + if (!S.getLangOpts().Modules) return; // Empty sets are uninteresting. @@ -1790,16 +1830,23 @@ static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context, NamedDecl *Old = Filter.next(); // Non-hidden declarations are never ignored. - if (!Old->isHidden()) + if (S.isVisible(Old)) continue; // Declarations of the same entity are not ignored, even if they have // different linkages. - if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) - if (Context.hasSameType(OldTD->getUnderlyingType(), - Decl->getUnderlyingType())) + if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) { + if (S.Context.hasSameType(OldTD->getUnderlyingType(), + Decl->getUnderlyingType())) continue; + // If both declarations give a tag declaration a typedef name for linkage + // purposes, then they declare the same entity. + if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) && + Decl->getAnonDeclWithTypedefName()) + continue; + } + if (!Old->isExternallyVisible()) Filter.erase(); } @@ -1909,6 +1956,27 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { if (Old->isInvalidDecl()) return New->setInvalidDecl(); + if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) { + auto *OldTag = OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true); + auto *NewTag = New->getAnonDeclWithTypedefName(); + NamedDecl *Hidden = nullptr; + if (getLangOpts().CPlusPlus && OldTag && NewTag && + OldTag->getCanonicalDecl() != NewTag->getCanonicalDecl() && + !hasVisibleDefinition(OldTag, &Hidden)) { + // There is a definition of this tag, but it is not visible. Use it + // instead of our tag. + New->setTypeForDecl(OldTD->getTypeForDecl()); + if (OldTD->isModed()) + New->setModedTypeSourceInfo(OldTD->getTypeSourceInfo(), + OldTD->getUnderlyingType()); + else + New->setTypeSourceInfo(OldTD->getTypeSourceInfo()); + + // Make the old tag definition visible. + makeMergedDefinitionVisible(Hidden, NewTag->getLocation()); + } + } + // If the typedef types are not identical, reject them in all languages and // with any extensions enabled. if (isIncompatibleTypedef(Old, New)) @@ -1978,7 +2046,6 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { Diag(New->getLocation(), diag::ext_redefinition_of_typedef) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); - return; } /// DeclhasAttr - returns true if decl Declaration already has the target @@ -2643,7 +2710,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, // UndefinedButUsed. if (!Old->isInlined() && New->isInlined() && !New->hasAttr<GNUInlineAttr>() && - (getLangOpts().CPlusPlus || !getLangOpts().GNUInline) && + !getLangOpts().GNUInline && Old->isUsed(false) && !Old->isDefined() && !New->isThisDeclarationADefinition()) UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(), @@ -2761,6 +2828,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, << New << New->getType(); } Diag(OldLocation, PrevDiag) << Old << Old->getType(); + return true; // Complain if this is an explicit declaration of a special // member that was initially declared implicitly. @@ -3336,14 +3404,23 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { } // C++ doesn't have tentative definitions, so go right ahead and check here. - const VarDecl *Def; + VarDecl *Def; if (getLangOpts().CPlusPlus && New->isThisDeclarationADefinition() == VarDecl::Definition && (Def = Old->getDefinition())) { - Diag(New->getLocation(), diag::err_redefinition) << New; - Diag(Def->getLocation(), diag::note_previous_definition); - New->setInvalidDecl(); - return; + NamedDecl *Hidden = nullptr; + if (!hasVisibleDefinition(Def, &Hidden) && + (New->getDescribedVarTemplate() || + New->getNumTemplateParameterLists() || + New->getDeclContext()->isDependentContext())) { + // The previous definition is hidden, and multiple definitions are + // permitted (in separate TUs). Form another definition of it. + } else { + Diag(New->getLocation(), diag::err_redefinition) << New; + Diag(Def->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return; + } } if (haveIncompatibleLanguageLinkages(Old, New)) { @@ -3375,8 +3452,20 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg()); } -static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) { - if (!S.Context.getLangOpts().CPlusPlus) +// The MS ABI changed between VS2013 and VS2015 with regard to numbers used to +// disambiguate entities defined in different scopes. +// While the VS2015 ABI fixes potential miscompiles, it is also breaks +// compatibility. +// We will pick our mangling number depending on which version of MSVC is being +// targeted. +static unsigned getMSManglingNumber(const LangOptions &LO, Scope *S) { + return LO.isCompatibleWithMSVC(LangOptions::MSVC2015) + ? S->getMSCurManglingNumber() + : S->getMSLastManglingNumber(); +} + +void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) { + if (!Context.getLangOpts().CPlusPlus) return; if (isa<CXXRecordDecl>(Tag->getParent())) { @@ -3385,21 +3474,62 @@ static void HandleTagNumbering(Sema &S, const TagDecl *Tag, Scope *TagScope) { if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl()) return; MangleNumberingContext &MCtx = - S.Context.getManglingNumberContext(Tag->getParent()); - S.Context.setManglingNumber( - Tag, MCtx.getManglingNumber(Tag, TagScope->getMSLocalManglingNumber())); + Context.getManglingNumberContext(Tag->getParent()); + Context.setManglingNumber( + Tag, MCtx.getManglingNumber( + Tag, getMSManglingNumber(getLangOpts(), TagScope))); return; } // If this tag isn't a direct child of a class, number it if it is local. Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = - S.getCurrentMangleNumberContext(Tag->getDeclContext(), - ManglingContextDecl)) { - S.Context.setManglingNumber( - Tag, - MCtx->getManglingNumber(Tag, TagScope->getMSLocalManglingNumber())); + if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( + Tag->getDeclContext(), ManglingContextDecl)) { + Context.setManglingNumber( + Tag, MCtx->getManglingNumber( + Tag, getMSManglingNumber(getLangOpts(), TagScope))); + } +} + +void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, + TypedefNameDecl *NewTD) { + // 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()) + return; + if (TagFromDeclSpec->getTypedefNameForAnonDecl()) + return; + + // A well-formed anonymous tag must always be a TUK_Definition. + assert(TagFromDeclSpec->isThisDeclarationADefinition()); + + // The type must match the tag exactly; no qualifiers allowed. + if (!Context.hasSameType(NewTD->getUnderlyingType(), + Context.getTagDeclType(TagFromDeclSpec))) + return; + + // If we've already computed linkage for the anonymous tag, then + // adding a typedef name for the anonymous decl can change that + // linkage, which might be a serious problem. Diagnose this as + // unsupported and ignore the typedef name. TODO: we should + // pursue this as a language defect and establish a formal rule + // for how to handle it. + if (TagFromDeclSpec->hasLinkageBeenComputed()) { + Diag(NewTD->getLocation(), diag::err_typedef_changes_linkage); + + SourceLocation tagLoc = TagFromDeclSpec->getInnerLocStart(); + tagLoc = getLocForEndOfToken(tagLoc); + + llvm::SmallString<40> textToInsert; + textToInsert += ' '; + textToInsert += NewTD->getIdentifier()->getName(); + Diag(tagLoc, diag::note_typedef_changes_linkage) + << FixItHint::CreateInsertion(tagLoc, textToInsert); + return; } + + // Otherwise, set this is the anon-decl typedef for the tag. + TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); } /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with @@ -3431,7 +3561,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } if (Tag) { - HandleTagNumbering(*this, Tag, S); + handleTagNumbering(Tag, S); Tag->setFreeStanding(); if (Tag->isInvalidDecl()) return Tag; @@ -3471,7 +3601,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return ActOnFriendTypeDecl(S, DS, TemplateParams); } - CXXScopeSpec &SS = DS.getTypeSpecScope(); + const CXXScopeSpec &SS = DS.getTypeSpecScope(); bool IsExplicitSpecialization = !TemplateParams.empty() && TemplateParams.back()->size() == 0; if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() && @@ -3498,7 +3628,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { if (getLangOpts().CPlusPlus || Record->getDeclContext()->isRecord()) - return BuildAnonymousStructOrUnion(S, DS, AS, Record, Context.getPrintingPolicy()); + return BuildAnonymousStructOrUnion(S, DS, AS, Record, + Context.getPrintingPolicy()); DeclaresAnything = false; } @@ -3726,8 +3857,7 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, // anonymous union is declared. unsigned OldChainingSize = Chaining.size(); if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD)) - for (auto *PI : IF->chain()) - Chaining.push_back(PI); + Chaining.append(IF->chain_begin(), IF->chain_end()); else Chaining.push_back(VD); @@ -4054,10 +4184,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (VarDecl *NewVD = dyn_cast<VarDecl>(Anon)) { if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = - getCurrentMangleNumberContext(NewVD->getDeclContext(), - ManglingContextDecl)) { - Context.setManglingNumber(NewVD, MCtx->getManglingNumber(NewVD, S->getMSLocalManglingNumber())); + if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( + NewVD->getDeclContext(), ManglingContextDecl)) { + Context.setManglingNumber( + NewVD, MCtx->getManglingNumber( + NewVD, getMSManglingNumber(getLangOpts(), S))); Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD)); } } @@ -4767,6 +4898,8 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, static void FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) { + SrcTL = SrcTL.getUnqualifiedLoc(); + DstTL = DstTL.getUnqualifiedLoc(); if (PointerTypeLoc SrcPTL = SrcTL.getAs<PointerTypeLoc>()) { PointerTypeLoc DstPTL = DstTL.castAs<PointerTypeLoc>(); FixInvalidVariablyModifiedTypeLoc(SrcPTL.getPointeeLoc(), @@ -4823,27 +4956,13 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) { return; // Note that we have a locally-scoped external with this name. - // FIXME: There can be multiple such declarations if they are functions marked - // __attribute__((overloadable)) declared in function scope in C. - LocallyScopedExternCDecls[ND->getDeclName()] = ND; + Context.getExternCContextDecl()->makeDeclVisibleInContext(ND); } NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) { - if (ExternalSource) { - // Load locally-scoped external decls from the external source. - // FIXME: This is inefficient. Maybe add a DeclContext for extern "C" decls? - SmallVector<NamedDecl *, 4> Decls; - ExternalSource->ReadLocallyScopedExternCDecls(Decls); - for (unsigned I = 0, N = Decls.size(); I != N; ++I) { - llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = LocallyScopedExternCDecls.find(Decls[I]->getDeclName()); - if (Pos == LocallyScopedExternCDecls.end()) - LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I]; - } - } - - NamedDecl *D = LocallyScopedExternCDecls.lookup(Name); - return D ? D->getMostRecentDecl() : nullptr; + // FIXME: We can have multiple results via __attribute__((overloadable)). + auto Result = Context.getExternCContextDecl()->lookup(Name); + return Result.empty() ? nullptr : *Result.begin(); } /// \brief Diagnose function specifiers on a declaration of an identifier that @@ -4955,7 +5074,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, // in an outer scope, it isn't the same thing. FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/false, /*AllowInlineNamespace*/false); - filterNonConflictingPreviousTypedefDecls(Context, NewTD, Previous); + filterNonConflictingPreviousTypedefDecls(*this, NewTD, Previous); if (!Previous.empty()) { Redeclaration = true; MergeTypedefNameDecl(NewTD, Previous); @@ -5102,14 +5221,27 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { if (ND.isExternallyVisible()) { S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static); ND.dropAttr<WeakRefAttr>(); + ND.dropAttr<AliasAttr>(); } } - // 'selectany' only applies to externally visible varable declarations. + if (auto *VD = dyn_cast<VarDecl>(&ND)) { + if (VD->hasInit()) { + if (const auto *Attr = VD->getAttr<AliasAttr>()) { + assert(VD->isThisDeclarationADefinition() && + !VD->isExternallyVisible() && "Broken AliasAttr handled late!"); + S.Diag(Attr->getLocation(), diag::err_alias_is_definition) << VD; + VD->dropAttr<AliasAttr>(); + } + } + } + + // 'selectany' only applies to externally visible variable declarations. // It does not apply to functions. if (SelectAnyAttr *Attr = ND.getAttr<SelectAnyAttr>()) { if (isa<FunctionDecl>(ND) || !ND.isExternallyVisible()) { - S.Diag(Attr->getLocation(), diag::err_attribute_selectany_non_extern_data); + S.Diag(Attr->getLocation(), + diag::err_attribute_selectany_non_extern_data); ND.dropAttr<SelectAnyAttr>(); } } @@ -5565,8 +5697,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } } else { - assert(D.getName().getKind() != UnqualifiedId::IK_TemplateId && - "should have a 'template<>' for this decl"); + assert( + (Invalid || D.getName().getKind() != UnqualifiedId::IK_TemplateId) && + "should have a 'template<>' for this decl"); } if (IsVariableTemplateSpecialization) { @@ -5627,6 +5760,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (IsLocalExternDecl) NewVD->setLocalExternDecl(); + bool EmitTLSUnsupportedError = false; if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) { // C++11 [dcl.stc]p4: // When thread_local is applied to a variable of block scope the @@ -5641,10 +5775,20 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_thread_non_global) << DeclSpec::getSpecifierName(TSCS); - else if (!Context.getTargetInfo().isTLSSupported()) - Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), - diag::err_thread_unsupported); - else + else if (!Context.getTargetInfo().isTLSSupported()) { + if (getLangOpts().CUDA) { + // Postpone error emission until we've collected attributes required to + // figure out whether it's a host or device variable and whether the + // error should be ignored. + EmitTLSUnsupportedError = true; + // We still need to mark the variable as TLS so it shows up in AST with + // proper storage class for other tools to use even if we're not going + // to emit any code for it. + NewVD->setTSCSpec(TSCS); + } else + Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_thread_unsupported); + } else NewVD->setTSCSpec(TSCS); } @@ -5693,6 +5837,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, ProcessDeclAttributes(S, NewVD, D); if (getLangOpts().CUDA) { + if (EmitTLSUnsupportedError && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) + Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_thread_unsupported); // CUDA B.2.5: "__shared__ and __constant__ variables have implied static // storage [duration]." if (SC == SC_None && S->getFnParent() != nullptr && @@ -5845,11 +5992,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = - getCurrentMangleNumberContext(NewVD->getDeclContext(), - ManglingContextDecl)) { + if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( + NewVD->getDeclContext(), ManglingContextDecl)) { Context.setManglingNumber( - NewVD, MCtx->getManglingNumber(NewVD, S->getMSLocalManglingNumber())); + NewVD, MCtx->getManglingNumber( + NewVD, getMSManglingNumber(getLangOpts(), S))); Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD)); } } @@ -6243,7 +6390,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { Previous.setShadowed(); // Filter out any non-conflicting previous declarations. - filterNonConflictingPreviousDecls(Context, NewVD, Previous); + filterNonConflictingPreviousDecls(*this, NewVD, Previous); if (!Previous.empty()) { MergeVarDecl(NewVD, Previous); @@ -6898,8 +7045,10 @@ static void checkIsValidOpenCLKernelParameter( // We have an error, now let's go back up through history and show where // the offending field came from - for (ArrayRef<const FieldDecl *>::const_iterator I = HistoryStack.begin() + 1, - E = HistoryStack.end(); I != E; ++I) { + for (ArrayRef<const FieldDecl *>::const_iterator + I = HistoryStack.begin() + 1, + E = HistoryStack.end(); + I != E; ++I) { const FieldDecl *OuterField = *I; S.Diag(OuterField->getLocation(), diag::note_within_field_of_type) << OuterField->getType(); @@ -7010,12 +7159,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Check that we can declare a template here. if (CheckTemplateDeclScope(S, TemplateParams)) - return nullptr; + NewFD->setInvalidDecl(); // A destructor cannot be a template. if (Name.getNameKind() == DeclarationName::CXXDestructorName) { Diag(NewFD->getLocation(), diag::err_destructor_template); - return nullptr; + NewFD->setInvalidDecl(); } // If we're adding a template to a dependent context, we may need to @@ -7347,7 +7496,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setInvalidDecl(); } - if (D.isFunctionDefinition() && CodeSegStack.CurrentValue && + // Apply an implicit SectionAttr if #pragma code_seg is active. + if (CodeSegStack.CurrentValue && D.isFunctionDefinition() && !NewFD->hasAttr<SectionAttr>()) { NewFD->addAttr( SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate, @@ -7363,23 +7513,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Handle attributes. ProcessDeclAttributes(S, NewFD, D); - QualType RetType = NewFD->getReturnType(); - const CXXRecordDecl *Ret = RetType->isRecordType() ? - RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl(); - if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() && - Ret && Ret->hasAttr<WarnUnusedResultAttr>()) { - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); - // Attach WarnUnusedResult to functions returning types with that attribute. - // Don't apply the attribute to that type's own non-static member functions - // (to avoid warning on things like assignment operators) - if (!MD || MD->getParent() != Ret) - NewFD->addAttr(WarnUnusedResultAttr::CreateImplicit(Context)); - } - if (getLangOpts().OpenCL) { // OpenCL v1.1 s6.5: Using an address space qualifier in a function return // type declaration will generate a compilation error. - unsigned AddressSpace = RetType.getAddressSpace(); + unsigned AddressSpace = NewFD->getReturnType().getAddressSpace(); if (AddressSpace == LangAS::opencl_local || AddressSpace == LangAS::opencl_global || AddressSpace == LangAS::opencl_constant) { @@ -7402,7 +7539,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization)); else if (!Previous.empty()) - // Make graceful recovery from an invalid redeclaration. + // Recover gracefully from an invalid redeclaration. D.setRedeclaration(true); assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && @@ -7543,6 +7680,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!NewFD->isInvalidDecl()) D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization)); + else if (!Previous.empty()) + // Recover gracefully from an invalid redeclaration. + D.setRedeclaration(true); } assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || @@ -7799,7 +7939,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, !Previous.isShadowed(); // Filter out any non-conflicting previous declarations. - filterNonConflictingPreviousDecls(Context, NewFD, Previous); + filterNonConflictingPreviousDecls(*this, NewFD, Previous); bool Redeclaration = false; NamedDecl *OldDecl = nullptr; @@ -7854,7 +7994,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // Check for a previous extern "C" declaration with this name. if (!Redeclaration && checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) { - filterNonConflictingPreviousDecls(Context, NewFD, Previous); + filterNonConflictingPreviousDecls(*this, NewFD, Previous); if (!Previous.empty()) { // This is an extern "C" declaration with the same name as a previous // declaration, and thus redeclares that entity... @@ -7952,28 +8092,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // This needs to happen first so that 'inline' propagates. NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl)); - if (isa<CXXMethodDecl>(NewFD)) { - // A valid redeclaration of a C++ method must be out-of-line, - // but (unfortunately) it's not necessarily a definition - // because of templates, which means that the previous - // declaration is not necessarily from the class definition. - - // For just setting the access, that doesn't matter. - CXXMethodDecl *oldMethod = cast<CXXMethodDecl>(OldDecl); - NewFD->setAccess(oldMethod->getAccess()); - - // Update the key-function state if necessary for this ABI. - if (NewFD->isInlined() && - !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { - // setNonKeyFunction needs to work with the original - // declaration from the class definition, and isVirtual() is - // just faster in that case, so map back to that now. - oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDecl()); - if (oldMethod->isVirtual()) { - Context.setNonKeyFunction(oldMethod); - } - } - } + if (isa<CXXMethodDecl>(NewFD)) + NewFD->setAccess(OldDecl->getAccess()); } } @@ -8153,6 +8273,12 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { bool HasExtraParameters = (nparams > 3); + if (FTP->isVariadic()) { + Diag(FD->getLocation(), diag::ext_variadic_main); + // FIXME: if we had information about the location of the ellipsis, we + // could add a FixIt hint to remove it as a parameter. + } + // Darwin passes an undocumented fourth argument of type char**. If // other platforms start sprouting these, the logic below will start // getting shifty. @@ -8543,8 +8669,13 @@ namespace { diag = diag::warn_uninit_self_reference_in_reference_init; } else if (cast<VarDecl>(OrigDecl)->isStaticLocal()) { diag = diag::warn_static_self_reference_in_init; - } else { + } else if (isa<TranslationUnitDecl>(OrigDecl->getDeclContext()) || + isa<NamespaceDecl>(OrigDecl->getDeclContext()) || + DRE->getDecl()->getType()->isRecordType()) { diag = diag::warn_uninit_self_reference_in_init; + } else { + // Local variables will be handled by the CFG analysis. + return; } S.DiagRuntimeBehavior(DRE->getLocStart(), DRE, @@ -8586,7 +8717,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // If there is no declaration, there was an error parsing it. Just ignore // the initializer. if (!RealDecl || RealDecl->isInvalidDecl()) { - CorrectDelayedTyposInExpr(Init); + CorrectDelayedTyposInExpr(Init, dyn_cast_or_null<VarDecl>(RealDecl)); return; } @@ -8617,6 +8748,21 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) { + // Attempt typo correction early so that the type of the init expression can + // be deduced based on the chosen correction:if the original init contains a + // TypoExpr. + ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl); + if (!Res.isUsable()) { + RealDecl->setInvalidDecl(); + return; + } + + if (Res.get() != Init) { + Init = Res.get(); + if (CXXDirectInit) + CXXDirectInit = dyn_cast<ParenListExpr>(Init); + } + Expr *DeduceInit = Init; // Initializer could be a C++ direct-initializer. Deduction only works if it // contains exactly one expression. @@ -8746,16 +8892,24 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->setInvalidDecl(); } - const VarDecl *Def; + VarDecl *Def; if ((Def = VDecl->getDefinition()) && Def != VDecl) { - Diag(VDecl->getLocation(), diag::err_redefinition) - << VDecl->getDeclName(); - Diag(Def->getLocation(), diag::note_previous_definition); - VDecl->setInvalidDecl(); - return; + NamedDecl *Hidden = nullptr; + if (!hasVisibleDefinition(Def, &Hidden) && + (VDecl->getDescribedVarTemplate() || + VDecl->getNumTemplateParameterLists() || + VDecl->getDeclContext()->isDependentContext())) { + // The previous definition is hidden, and multiple definitions are + // permitted (in separate TUs). Form another definition of it. + } else { + Diag(VDecl->getLocation(), diag::err_redefinition) + << VDecl->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + VDecl->setInvalidDecl(); + return; + } } - const VarDecl *PrevInit = nullptr; if (getLangOpts().CPlusPlus) { // C++ [class.static.data]p4 // If a static data member is of const integral or const @@ -8769,10 +8923,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // We already performed a redefinition check above, but for static // data members we also need to check whether there was an in-class // declaration with an initializer. - if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) { + if (VDecl->isStaticDataMember() && VDecl->getCanonicalDecl()->hasInit()) { Diag(Init->getExprLoc(), diag::err_static_data_member_reinitialization) << VDecl->getDeclName(); - Diag(PrevInit->getInit()->getExprLoc(), diag::note_previous_initializer) << 0; + Diag(VDecl->getCanonicalDecl()->getInit()->getExprLoc(), + diag::note_previous_initializer) + << 0; return; } @@ -8829,8 +8985,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // Try to correct any TypoExprs in the initialization arguments. for (size_t Idx = 0; Idx < Args.size(); ++Idx) { - ExprResult Res = - CorrectDelayedTyposInExpr(Args[Idx], [this, Entity, Kind](Expr *E) { + ExprResult Res = CorrectDelayedTyposInExpr( + Args[Idx], VDecl, [this, Entity, Kind](Expr *E) { InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E)); return Init.Failed() ? ExprError() : E; }); @@ -9253,6 +9409,8 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, Var->setInvalidDecl(); return; } + } else { + return; } // The variable can not have an abstract class type. @@ -9350,8 +9508,6 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) { case SC_OpenCLWorkGroupLocal: llvm_unreachable("Unexpected storage class"); } - if (VD->isConstexpr()) - Error = 5; if (Error != -1) { Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) << VD->getDeclName() << Error; @@ -9453,7 +9609,9 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } - if (var->isThisDeclarationADefinition() && + // Apply section attributes and pragmas to global variables. + bool GlobalStorage = var->hasGlobalStorage(); + if (GlobalStorage && var->isThisDeclarationADefinition() && ActiveTemplateInstantiations.empty()) { PragmaStack<StringLiteral *> *Stack = nullptr; int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read; @@ -9466,11 +9624,11 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { Stack = &DataSegStack; SectionFlags |= ASTContext::PSF_Write; } - if (!var->hasAttr<SectionAttr>() && Stack->CurrentValue) - var->addAttr( - SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate, - Stack->CurrentValue->getString(), - Stack->CurrentPragmaLocation)); + if (Stack->CurrentValue && !var->hasAttr<SectionAttr>()) { + var->addAttr(SectionAttr::CreateImplicit( + Context, SectionAttr::Declspec_allocate, + Stack->CurrentValue->getString(), Stack->CurrentPragmaLocation)); + } if (const SectionAttr *SA = var->getAttr<SectionAttr>()) if (UnifySection(SA->getName(), SectionFlags, var)) var->dropAttr<SectionAttr>(); @@ -9513,7 +9671,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } Expr *Init = var->getInit(); - bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal(); + bool IsGlobal = GlobalStorage && !var->isStaticLocal(); QualType baseType = Context.getBaseElementType(type); if (!var->getDeclContext()->isDependentContext() && @@ -9625,18 +9783,6 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { } } - if (!VD->isInvalidDecl() && - VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) { - if (const VarDecl *Def = VD->getDefinition()) { - if (Def->hasAttr<AliasAttr>()) { - Diag(VD->getLocation(), diag::err_tentative_after_alias) - << VD->getDeclName(); - Diag(Def->getLocation(), diag::note_previous_definition); - VD->setInvalidDecl(); - } - } - } - const DeclContext *DC = VD->getDeclContext(); // If there's a #pragma GCC visibility in scope, and this isn't a class // member, set the visibility of this variable. @@ -9699,7 +9845,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (DeclSpec::isDeclRep(DS.getTypeSpecType())) { if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) { - HandleTagNumbering(*this, Tag, S); + handleTagNumbering(Tag, S); if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl()) Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup); } @@ -9766,9 +9912,12 @@ void Sema::ActOnDocumentableDecl(Decl *D) { void Sema::ActOnDocumentableDecls(ArrayRef<Decl *> Group) { // Don't parse the comment if Doxygen diagnostics are ignored. if (Group.empty() || !Group[0]) - return; + return; - if (Diags.isIgnored(diag::warn_doc_param_not_found, Group[0]->getLocation())) + if (Diags.isIgnored(diag::warn_doc_param_not_found, + Group[0]->getLocation()) && + Diags.isIgnored(diag::warn_unknown_comment_command_name, + Group[0]->getLocation())) return; if (Group.size() >= 2) { @@ -10058,7 +10207,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, << " int " << FTI.Params[i].Ident->getName() << ";\n"; Diag(FTI.Params[i].IdentLoc, diag::ext_param_not_declared) << FTI.Params[i].Ident - << FixItHint::CreateInsertion(LocAfterDecls, Code.str()); + << FixItHint::CreateInsertion(LocAfterDecls, Code); // Implicitly declare the argument as type 'int' for lack of a better // type. @@ -10127,6 +10276,10 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, if (FD->hasAttr<OpenCLKernelAttr>()) return false; + // Don't warn on explicitly deleted functions. + if (FD->isDeleted()) + return false; + bool MissingPrototype = true; for (const FunctionDecl *Prev = FD->getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) { @@ -10157,6 +10310,18 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, if (canRedefineFunction(Definition, getLangOpts())) return; + // If we don't have a visible definition of the function, and it's inline or + // a template, it's OK to form another definition of it. + // + // FIXME: Should we skip the body of the function and use the old definition + // in this case? That may be necessary for functions that return local types + // through a deduced return type, or instantiate templates with local types. + if (!hasVisibleDefinition(Definition) && + (Definition->isInlineSpecified() || + Definition->getDescribedFunctionTemplate() || + Definition->getNumTemplateParameterLists())) + return; + if (getLangOpts().GNUMode && Definition->isInlineSpecified() && Definition->getStorageClass() == SC_Extern) Diag(FD->getLocation(), diag::err_redefinition_extern_inline) @@ -10269,30 +10434,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { diag::err_func_def_incomplete_result)) FD->setInvalidDecl(); - // GNU warning -Wmissing-prototypes: - // Warn if a global function is defined without a previous - // prototype declaration. This warning is issued even if the - // definition itself provides a prototype. The aim is to detect - // global functions that fail to be declared in header files. - const FunctionDecl *PossibleZeroParamPrototype = nullptr; - if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) { - Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; - - if (PossibleZeroParamPrototype) { - // We found a declaration that is not a prototype, - // but that could be a zero-parameter prototype - if (TypeSourceInfo *TI = - PossibleZeroParamPrototype->getTypeSourceInfo()) { - TypeLoc TL = TI->getTypeLoc(); - if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>()) - Diag(PossibleZeroParamPrototype->getLocation(), - diag::note_declaration_not_a_prototype) - << PossibleZeroParamPrototype - << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); - } - } - } - if (FnBodyScope) PushDeclContext(FnBodyScope, FD); @@ -10321,9 +10462,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { I != E; ++I) { NamedDecl *D = *I; - // Some of these decls (like enums) may have been pinned to the translation unit - // for lack of a real context earlier. If so, remove from the translation unit - // and reattach to the current context. + // Some of these decls (like enums) may have been pinned to the + // translation unit for lack of a real context earlier. If so, remove + // from the translation unit and reattach to the current context. if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) { // Is the decl actually in the context? for (const auto *DI : Context.getTranslationUnitDecl()->decls()) { @@ -10468,6 +10609,23 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, Context.adjustDeducedFunctionResultType( FD, SubstAutoType(ResultType.getType(), Context.VoidTy)); } + } else if (getLangOpts().CPlusPlus11 && isLambdaCallOperator(FD)) { + auto *LSI = getCurLambda(); + if (LSI->HasImplicitReturnType) { + deduceClosureReturnType(*LSI); + + // C++11 [expr.prim.lambda]p4: + // [...] if there are no return statements in the compound-statement + // [the deduced type is] the type void + QualType RetType = + LSI->ReturnType.isNull() ? Context.VoidTy : LSI->ReturnType; + + // Update the return type to the deduced type. + const FunctionProtoType *Proto = + FD->getType()->getAs<FunctionProtoType>(); + FD->setType(Context.getFunctionType(RetType, Proto->getParamTypes(), + Proto->getExtProtoInfo())); + } } // The only way to be included in UndefinedButUsed is if there is an @@ -10477,7 +10635,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (!FD->isExternallyVisible()) UndefinedButUsed.erase(FD); else if (FD->isInlined() && - (LangOpts.CPlusPlus || !LangOpts.GNUInline) && + !LangOpts.GNUInline && (!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>())) UndefinedButUsed.erase(FD); } @@ -10494,7 +10652,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (!FD->isInvalidDecl()) { // Don't diagnose unused parameters of defaulted or deleted functions. - if (Body) + if (!FD->isDeleted() && !FD->isDefaulted()) DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(), FD->getReturnType(), FD); @@ -10512,7 +10670,55 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, !FD->isDependentContext()) computeNRVO(Body, getCurFunction()); } - + + // GNU warning -Wmissing-prototypes: + // Warn if a global function is defined without a previous + // prototype declaration. This warning is issued even if the + // definition itself provides a prototype. The aim is to detect + // global functions that fail to be declared in header files. + const FunctionDecl *PossibleZeroParamPrototype = nullptr; + if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) { + Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; + + if (PossibleZeroParamPrototype) { + // We found a declaration that is not a prototype, + // but that could be a zero-parameter prototype + if (TypeSourceInfo *TI = + PossibleZeroParamPrototype->getTypeSourceInfo()) { + TypeLoc TL = TI->getTypeLoc(); + if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>()) + Diag(PossibleZeroParamPrototype->getLocation(), + diag::note_declaration_not_a_prototype) + << PossibleZeroParamPrototype + << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); + } + } + } + + if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { + const CXXMethodDecl *KeyFunction; + if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) && + MD->isVirtual() && + (KeyFunction = Context.getCurrentKeyFunction(MD->getParent())) && + MD == KeyFunction->getCanonicalDecl()) { + // Update the key-function state if necessary for this ABI. + if (FD->isInlined() && + !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { + Context.setNonKeyFunction(MD); + + // If the newly-chosen key function is already defined, then we + // need to mark the vtable as used retroactively. + KeyFunction = Context.getCurrentKeyFunction(MD->getParent()); + const FunctionDecl *Definition; + if (KeyFunction && KeyFunction->isDefined(Definition)) + MarkVTableUsed(Definition->getLocation(), MD->getParent(), true); + } else { + // We just defined they key function; mark the vtable as used. + MarkVTableUsed(FD->getLocation(), MD->getParent(), true); + } + } + } + assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { @@ -10561,7 +10767,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (getCurFunction()->ObjCWarnForNoInitDelegation) { // Don't issue this warning for unavaialable inits. if (!MD->isUnavailable()) - Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call); + Diag(MD->getLocation(), + diag::warn_objc_secondary_init_missing_init_call); getCurFunction()->ObjCWarnForNoInitDelegation = false; } } else { @@ -10573,7 +10780,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, "handled in the block above."); // Verify and clean out per-function state. - if (Body) { + if (Body && (!FD || !FD->isDefaulted())) { // C++ constructors that have function-try-blocks can't have return // statements in the handlers of that block. (C++ [except.handle]p14) // Verify this. @@ -10623,8 +10830,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } } - assert(ExprCleanupObjects.size() == ExprEvalContexts.back().NumCleanupObjects - && "Leftover temporaries in function"); + assert(ExprCleanupObjects.size() == + ExprEvalContexts.back().NumCleanupObjects && + "Leftover temporaries in function"); assert(!ExprNeedsCleanups && "Unaccounted cleanups in function"); assert(MaybeODRUseExprs.empty() && "Leftover expressions for odr-use checking"); @@ -10888,44 +11096,10 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, case TST_union: case TST_class: { TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); - - // Do nothing if the tag is not anonymous or already has an - // associated typedef (from an earlier typedef in this decl group). - if (tagFromDeclSpec->getIdentifier()) break; - if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break; - - // A well-formed anonymous tag must always be a TUK_Definition. - assert(tagFromDeclSpec->isThisDeclarationADefinition()); - - // The type must match the tag exactly; no qualifiers allowed. - if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec))) - break; - - // If we've already computed linkage for the anonymous tag, then - // adding a typedef name for the anonymous decl can change that - // linkage, which might be a serious problem. Diagnose this as - // unsupported and ignore the typedef name. TODO: we should - // pursue this as a language defect and establish a formal rule - // for how to handle it. - if (tagFromDeclSpec->hasLinkageBeenComputed()) { - Diag(D.getIdentifierLoc(), diag::err_typedef_changes_linkage); - - SourceLocation tagLoc = D.getDeclSpec().getTypeSpecTypeLoc(); - tagLoc = getLocForEndOfToken(tagLoc); - - llvm::SmallString<40> textToInsert; - textToInsert += ' '; - textToInsert += D.getIdentifier()->getName(); - Diag(tagLoc, diag::note_typedef_changes_linkage) - << FixItHint::CreateInsertion(tagLoc, textToInsert); - break; - } - - // Otherwise, set this is the anon-decl typedef for the tag. - tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); + setTagNameForLinkagePurposes(tagFromDeclSpec, NewTD); break; } - + default: break; } @@ -11146,13 +11320,16 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S, return FixItHint::CreateInsertion(NameLoc, Insertion); } -/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the +/// \brief This is invoked when we see 'struct foo' or 'struct {'. In the /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a /// reference/declaration/definition of a tag. /// -/// IsTypeSpecifier is true if this is a type-specifier (or +/// \param IsTypeSpecifier \c true if this is a type-specifier (or /// trailing-type-specifier) other than one in an alias-declaration. +/// +/// \param SkipBody If non-null, will be set to indicate if the caller should +/// skip the definition of this tag and treat it as if it were a declaration. Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -11163,7 +11340,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, - bool IsTypeSpecifier) { + bool IsTypeSpecifier, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. IdentifierInfo *OrigName = Name; assert((Name != nullptr || TUK == TUK_Definition) && @@ -11206,7 +11383,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, ModulePrivateLoc, /*FriendLoc*/SourceLocation(), TemplateParameterLists.size()-1, - TemplateParameterLists.data()); + TemplateParameterLists.data(), + SkipBody); return Result.get(); } else { // The "template<>" header is extraneous. @@ -11472,6 +11650,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } } + // If we have a known previous declaration to use, then use it. + if (Previous.empty() && SkipBody && SkipBody->Previous) + Previous.addDecl(SkipBody->Previous); + if (!Previous.empty()) { NamedDecl *PrevDecl = Previous.getFoundDecl(); NamedDecl *DirectPrevDecl = @@ -11589,7 +11771,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // Diagnose attempts to redefine a tag. if (TUK == TUK_Definition) { - if (TagDecl *Def = PrevTagDecl->getDefinition()) { + if (NamedDecl *Def = PrevTagDecl->getDefinition()) { // If we're defining a specialization and the previous definition // is from an implicit instantiation, don't emit an error // here; we'll catch this in the general case below. @@ -11605,7 +11787,18 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, TSK_ExplicitSpecialization; } - if (!IsExplicitSpecializationAfterInstantiation) { + NamedDecl *Hidden = nullptr; + if (SkipBody && getLangOpts().CPlusPlus && + !hasVisibleDefinition(Def, &Hidden)) { + // There is a definition of this tag, but it is not visible. We + // explicitly make use of C++'s one definition rule here, and + // assume that this definition is identical to the hidden one + // we already have. Make the existing definition visible and + // use it in place of this one. + SkipBody->ShouldSkip = true; + makeMergedDefinitionVisible(Hidden, KWLoc); + return Def; + } else if (!IsExplicitSpecializationAfterInstantiation) { // A redeclaration in function prototype scope in C isn't // visible elsewhere, so merely issue a warning. if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope()) @@ -12339,8 +12532,10 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, InvalidDecl = true; bool ZeroWidth = false; + if (InvalidDecl) + BitWidth = nullptr; // If this is declared as a bit-field, check the bit-field. - if (!InvalidDecl && BitWidth) { + if (BitWidth) { BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth, &ZeroWidth).get(); if (!BitWidth) { @@ -12354,7 +12549,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (!InvalidDecl && Mutable) { unsigned DiagID = 0; if (T->isReferenceType()) - DiagID = diag::err_mutable_reference; + DiagID = getLangOpts().MSVCCompat ? diag::ext_mutable_reference + : diag::err_mutable_reference; else if (T.isConstQualified()) DiagID = diag::err_mutable_const; @@ -12363,8 +12559,10 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid()) ErrLoc = D->getDeclSpec().getStorageClassSpecLoc(); Diag(ErrLoc, DiagID); - Mutable = false; - InvalidDecl = true; + if (DiagID != diag::ext_mutable_reference) { + Mutable = false; + InvalidDecl = true; + } } } @@ -13286,6 +13484,29 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, Val, EnumVal); } +Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, + SourceLocation IILoc) { + if (!getLangOpts().Modules || !getLangOpts().CPlusPlus) + return SkipBodyInfo(); + + // We have an anonymous enum definition. Look up the first enumerator to + // determine if we should merge the definition with an existing one and + // skip the body. + NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName, + ForRedeclaration); + auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl); + NamedDecl *Hidden; + if (PrevECD && + !hasVisibleDefinition(cast<NamedDecl>(PrevECD->getDeclContext()), + &Hidden)) { + SkipBodyInfo Skip; + Skip.ShouldSkip = true; + Skip.Previous = Hidden; + return Skip; + } + + return SkipBodyInfo(); +} Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, @@ -13528,6 +13749,49 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements, } } +bool +Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, + bool AllowMask) const { + FlagEnumAttr *FEAttr = ED->getAttr<FlagEnumAttr>(); + assert(FEAttr && "looking for value in non-flag enum"); + + llvm::APInt FlagMask = ~FEAttr->getFlagBits(); + unsigned Width = FlagMask.getBitWidth(); + + // We will try a zero-extended value for the regular check first. + llvm::APInt ExtVal = Val.zextOrSelf(Width); + + // A value is in a flag enum if either its bits are a subset of the enum's + // flag bits (the first condition) or we are allowing masks and the same is + // true of its complement (the second condition). When masks are allowed, we + // allow the common idiom of ~(enum1 | enum2) to be a valid enum value. + // + // While it's true that any value could be used as a mask, the assumption is + // that a mask will have all of the insignificant bits set. Anything else is + // likely a logic error. + if (!(FlagMask & ExtVal)) + return true; + + if (AllowMask) { + // Try a one-extended value instead. This can happen if the enum is wider + // than the constant used, in C with extensions to allow for wider enums. + // The mask will still have the correct behaviour, so we give the user the + // benefit of the doubt. + // + // FIXME: This heuristic can cause weird results if the enum was extended + // to a larger type and is signed, because then bit-masks of smaller types + // that get extended will fall out of range (e.g. ~0x1u). We currently don't + // detect that case and will get a false positive for it. In most cases, + // though, it can be fixed by making it a signed type (e.g. ~0x1), so it may + // be fine just to accept this as a warning. + ExtVal |= llvm::APInt::getHighBitsSet(Width, Width - Val.getBitWidth()); + if (!(FlagMask & ~ExtVal)) + return true; + } + + return false; +} + void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, SourceLocation RBraceLoc, Decl *EnumDeclX, ArrayRef<Decl *> Elements, @@ -13613,10 +13877,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, BestPromotionType = Context.getPromotedIntegerType(BestType); else BestPromotionType = BestType; - // We don't need to set BestWidth, because BestType is going to be the type - // of the enumerators, but we do anyway because otherwise some compilers - // warn that it might be used uninitialized. - BestWidth = CharWidth; + + BestWidth = Context.getIntWidth(BestType); } else if (NumNegativeBits) { // If there is a negative value, figure out the smallest integer type (of @@ -13681,10 +13943,15 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } } + FlagEnumAttr *FEAttr = Enum->getAttr<FlagEnumAttr>(); + if (FEAttr) + FEAttr->getFlagBits() = llvm::APInt(BestWidth, 0); + // Loop over all of the enumerator constants, changing their types to match - // the type of the enum if needed. - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]); + // the type of the enum if needed. If we have a flag type, we also prepare the + // FlagBits cache. + for (auto *D : Elements) { + auto *ECD = cast_or_null<EnumConstantDecl>(D); if (!ECD) continue; // Already issued a diagnostic. // Standard C says the enumerators have int type, but we allow, as an @@ -13714,7 +13981,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // enum-specifier, each enumerator has the type of its // enumeration. ECD->setType(EnumType); - continue; + goto flagbits; } else { NewTy = BestType; NewWidth = BestWidth; @@ -13741,8 +14008,32 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(EnumType); else ECD->setType(NewTy); + +flagbits: + // Check to see if we have a constant with exactly one bit set. Note that x + // & (x - 1) will be nonzero if and only if x has more than one bit set. + if (FEAttr) { + llvm::APInt ExtVal = InitVal.zextOrSelf(BestWidth); + if (ExtVal != 0 && !(ExtVal & (ExtVal - 1))) { + FEAttr->getFlagBits() |= ExtVal; + } + } } + if (FEAttr) { + for (Decl *D : Elements) { + EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(D); + if (!ECD) continue; // Already issued a diagnostic. + + llvm::APSInt InitVal = ECD->getInitVal(); + if (InitVal != 0 && !IsValueInFlagEnum(Enum, InitVal, true)) + Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range) + << ECD << Enum; + } + } + + + Enum->completeDefinition(BestType, BestPromotionType, NumPositiveBits, NumNegativeBits); @@ -13804,6 +14095,8 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, if (!Mod) return true; + VisibleModules.setVisible(Mod, ImportLoc); + checkModuleImportContext(*this, Mod, ImportLoc, CurContext); // FIXME: we should support importing a submodule within a different submodule @@ -13839,9 +14132,46 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext); - // FIXME: Should we synthesize an ImportDecl here? - getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc, - /*Complain=*/true); + // Determine whether we're in the #include buffer for a module. The #includes + // in that buffer do not qualify as module imports; they're just an + // implementation detail of us building the module. + // + // FIXME: Should we even get ActOnModuleInclude calls for those? + bool IsInModuleIncludes = + TUKind == TU_Module && + getSourceManager().isWrittenInMainFile(DirectiveLoc); + + // If this module import was due to an inclusion directive, create an + // implicit import declaration to capture it in the AST. + if (!IsInModuleIncludes) { + TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); + ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU, + DirectiveLoc, Mod, + DirectiveLoc); + TU->addDecl(ImportD); + Consumer.HandleImplicitImportDecl(ImportD); + } + + getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc); + VisibleModules.setVisible(Mod, DirectiveLoc); +} + +void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { + checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext); + + if (getLangOpts().ModulesLocalVisibility) + VisibleModulesStack.push_back(std::move(VisibleModules)); + VisibleModules.setVisible(Mod, DirectiveLoc); +} + +void Sema::ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod) { + checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext); + + if (getLangOpts().ModulesLocalVisibility) { + VisibleModules = std::move(VisibleModulesStack.back()); + VisibleModulesStack.pop_back(); + VisibleModules.setVisible(Mod, DirectiveLoc); + } } void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc, @@ -13858,8 +14188,8 @@ void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc, Consumer.HandleImplicitImportDecl(ImportD); // Make the module visible. - getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc, - /*Complain=*/false); + getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc); + VisibleModules.setVisible(Mod, Loc); } void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, @@ -13917,7 +14247,10 @@ Decl *Sema::getObjCDeclContext() const { } AvailabilityResult Sema::getCurContextAvailability() const { - const Decl *D = cast<Decl>(getCurObjCLexicalContext()); + const Decl *D = cast_or_null<Decl>(getCurObjCLexicalContext()); + if (!D) + return AR_Available; + // If we are within an Objective-C method, we should consult // both the availability of the method as well as the // enclosing class. If the class is (say) deprecated, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index d7ce6f1..31fe055 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -51,6 +51,11 @@ namespace AttributeLangSupport { static bool isFunctionOrMethod(const Decl *D) { return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D); } +/// \brief Return true if the given decl has function type (function or +/// function-typed variable) or an Objective-C method or a block. +static bool isFunctionOrMethodOrBlock(const Decl *D) { + return isFunctionOrMethod(D) || isa<BlockDecl>(D); +} /// Return true if the given decl has a declarator that should have /// been processed by Sema::GetTypeForDeclarator. @@ -257,7 +262,7 @@ static bool checkFunctionOrMethodParameterIndex(Sema &S, const Decl *D, unsigned AttrArgNum, const Expr *IdxExpr, uint64_t &Idx) { - assert(isFunctionOrMethod(D)); + assert(isFunctionOrMethodOrBlock(D)); // In C++ the implicit 'this' function parameter also counts. // Parameters are counted from one. @@ -351,13 +356,13 @@ static bool isIntOrBool(Expr *Exp) { // Check to see if the type is a smart pointer of some kind. We assume // it's a smart pointer if it defines both operator-> and operator*. static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { - DeclContextLookupConstResult Res1 = RT->getDecl()->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); + DeclContextLookupResult Res1 = RT->getDecl()->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); if (Res1.empty()) return false; - DeclContextLookupConstResult Res2 = RT->getDecl()->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); + DeclContextLookupResult Res2 = RT->getDecl()->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); if (Res2.empty()) return false; @@ -1492,6 +1497,20 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } + // Aliases should be on declarations, not definitions. + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->isThisDeclarationADefinition()) { + S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << FD; + return; + } + } else { + const auto *VD = cast<VarDecl>(D); + if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) { + S.Diag(Attr.getLoc(), diag::err_alias_is_definition) << VD; + return; + } + } + // FIXME: check if target symbol exists in current file D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, @@ -1534,18 +1553,16 @@ static void handleTLSModelAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - QualType RetTy = FD->getReturnType(); - if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { - D->addAttr(::new (S.Context) - MallocAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - return; - } +static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) { + QualType ResultType = getFunctionOrMethodResultType(D); + if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) { + D->addAttr(::new (S.Context) RestrictAttr( + Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); + return; } - S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only); + S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only) + << Attr.getName() << getFunctionOrMethodResultSourceRange(D); } static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1589,7 +1606,7 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, // The checking path for 'noreturn' and 'analyzer_noreturn' are different // because 'analyzer_noreturn' does not impact the type. - if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) { + if (!isFunctionOrMethodOrBlock(D)) { ValueDecl *VD = dyn_cast<ValueDecl>(D); if (!VD || (!VD->getType()->isBlockPointerType() && !VD->getType()->isFunctionPointerType())) { @@ -2105,6 +2122,22 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } +static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &Attr) { + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { + QualType T = TD->getUnderlyingType(); + if (!T->isObjCObjectPointerType()) { + S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute); + return; + } + } else { + S.Diag(D->getLocation(), diag::warn_independentclass_attribute); + return; + } + D->addAttr(::new (S.Context) + ObjCIndependentClassAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!Attr.isArgIdent(0)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) @@ -2330,6 +2363,15 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, AttrSpellingListIndex); } +bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) { + std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName); + if (!Error.empty()) { + Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error; + return false; + } + return true; +} + static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Make sure that there is a string literal as the sections's single // argument. @@ -2338,6 +2380,9 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc)) return; + if (!S.checkSectionName(LiteralLoc, Str)) + return; + // If the target wants to validate the section specifier, make it happen. std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str); if (!Error.empty()) { @@ -2482,6 +2527,7 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) { .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) .Case("kprintf", SupportedFormat) // OpenBSD. .Case("freebsd_kprintf", SupportedFormat) // FreeBSD. + .Case("os_trace", SupportedFormat) .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) .Default(InvalidFormat); @@ -2838,6 +2884,16 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) return; + if (E->isValueDependent()) { + if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) { + if (!TND->getUnderlyingType()->isDependentType()) { + S.Diag(Attr.getLoc(), diag::err_alignment_dependent_typedef_name) + << E->getSourceRange(); + return; + } + } + } + S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(), Attr.isPackExpansion()); } @@ -2940,12 +2996,15 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, void Sema::CheckAlignasUnderalignment(Decl *D) { assert(D->hasAttrs() && "no attributes on decl"); - QualType Ty; - if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) - Ty = VD->getType(); - else - Ty = Context.getTagDeclType(cast<TagDecl>(D)); - if (Ty->isDependentType() || Ty->isIncompleteType()) + QualType UnderlyingTy, DiagTy; + if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { + UnderlyingTy = DiagTy = VD->getType(); + } else { + UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D)); + if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) + UnderlyingTy = ED->getIntegerType(); + } + if (DiagTy->isDependentType() || DiagTy->isIncompleteType()) return; // C++11 [dcl.align]p5, C11 6.7.5/4: @@ -2964,10 +3023,10 @@ void Sema::CheckAlignasUnderalignment(Decl *D) { if (AlignasAttr && Align) { CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); - CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty); + CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy); if (NaturalAlign > RequestedAlign) Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) - << Ty << (unsigned)NaturalAlign.getQuantity(); + << DiagTy << (unsigned)NaturalAlign.getQuantity(); } } @@ -3315,11 +3374,6 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); return; } - case AttributeList::AT_PnaclCall: - D->addAttr(::new (S.Context) - PnaclCallAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); - return; case AttributeList::AT_IntelOclBicc: D->addAttr(::new (S.Context) IntelOclBiccAttr(Attr.getRange(), S.Context, @@ -3376,16 +3430,18 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, Diag(attr.getLoc(), diag::err_invalid_pcs); return true; } - case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break; case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; default: llvm_unreachable("unexpected attribute kind"); } const TargetInfo &TI = Context.getTargetInfo(); TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); - if (A == TargetInfo::CCCR_Warning) { - Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); + if (A != TargetInfo::CCCR_OK) { + if (A == TargetInfo::CCCR_Warning) + Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); + // This convention is not valid for the target. Use the default function or + // method calling convention. TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; if (FD) MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member : @@ -3432,20 +3488,63 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { return false; } +// Checks whether an argument of launch_bounds attribute is acceptable +// May output an error. +static bool checkLaunchBoundsArgument(Sema &S, Expr *E, + const CUDALaunchBoundsAttr &Attr, + const unsigned Idx) { + + if (S.DiagnoseUnexpandedParameterPack(E)) + return false; + + // Accept template arguments for now as they depend on something else. + // We'll get to check them when they eventually get instantiated. + if (E->isValueDependent()) + return true; + + llvm::APSInt I(64); + if (!E->isIntegerConstantExpr(I, S.Context)) { + S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) + << &Attr << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); + return false; + } + // Make sure we can fit it in 32 bits. + if (!I.isIntN(32)) { + S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false) + << 32 << /* Unsigned */ 1; + return false; + } + if (I < 0) + S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) + << &Attr << Idx << E->getSourceRange(); + + return true; +} + +void Sema::AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads, + Expr *MinBlocks, unsigned SpellingListIndex) { + CUDALaunchBoundsAttr TmpAttr(AttrRange, Context, MaxThreads, MinBlocks, + SpellingListIndex); + + if (!checkLaunchBoundsArgument(*this, MaxThreads, TmpAttr, 0)) + return; + + if (MinBlocks && !checkLaunchBoundsArgument(*this, MinBlocks, TmpAttr, 1)) + return; + + D->addAttr(::new (Context) CUDALaunchBoundsAttr( + AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex)); +} + static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr) { - uint32_t MaxThreads, MinBlocks = 0; - if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), MaxThreads, 1)) - return; - if (Attr.getNumArgs() > 1 && !checkUInt32Argument(S, Attr, - Attr.getArgAsExpr(1), - MinBlocks, 2)) + if (!checkAttributeAtLeastNumArgs(S, Attr, 1) || + !checkAttributeAtMostNumArgs(S, Attr, 2)) return; - D->addAttr(::new (S.Context) - CUDALaunchBoundsAttr(Attr.getRange(), S.Context, - MaxThreads, MinBlocks, - Attr.getAttributeSpellingListIndex())); + S.AddLaunchBoundsAttr(Attr.getRange(), D, Attr.getArgAsExpr(0), + Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr, + Attr.getAttributeSpellingListIndex()); } static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, @@ -3724,6 +3823,22 @@ static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D, S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0; return; } + + // Typedefs only allow objc_bridge(id) and have some additional checking. + if (auto TD = dyn_cast<TypedefNameDecl>(D)) { + if (!Parm->Ident->isStr("id")) { + S.Diag(Attr.getLoc(), diag::err_objc_attr_typedef_not_id) + << Attr.getName(); + return; + } + + // Only allow 'cv void *'. + QualType T = TD->getUnderlyingType(); + if (!T->isVoidPointerType()) { + S.Diag(Attr.getLoc(), diag::err_objc_attr_typedef_not_void_pointer); + return; + } + } D->addAttr(::new (S.Context) ObjCBridgeAttr(Attr.getRange(), S.Context, Parm->Ident, @@ -3770,6 +3885,10 @@ static void handleObjCDesignatedInitializer(Sema &S, Decl *D, IFace = CatDecl->getClassInterface(); else IFace = cast<ObjCInterfaceDecl>(D->getDeclContext()); + + if (!IFace) + return; + IFace->setHasDesignatedInitializers(); D->addAttr(::new (S.Context) ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context, @@ -4226,9 +4345,52 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } } + + if (!S.getLangOpts().CPlusPlus14) + if (Attr.isCXX11Attribute() && + !(Attr.hasScope() && Attr.getScopeName()->isStr("gnu"))) + S.Diag(Attr.getLoc(), diag::ext_deprecated_attr_is_a_cxx14_extension); + handleAttrWithMessage<DeprecatedAttr>(S, D, Attr); } +static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) + return; + + std::vector<std::string> Sanitizers; + + for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) { + StringRef SanitizerName; + SourceLocation LiteralLoc; + + if (!S.checkStringLiteralArgumentAttr(Attr, I, SanitizerName, &LiteralLoc)) + return; + + if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == 0) + S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName; + + Sanitizers.push_back(SanitizerName); + } + + D->addAttr(::new (S.Context) NoSanitizeAttr( + Attr.getRange(), S.Context, Sanitizers.data(), Sanitizers.size(), + Attr.getAttributeSpellingListIndex())); +} + +static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + std::string SanitizerName = + llvm::StringSwitch<std::string>(Attr.getName()->getName()) + .Case("no_address_safety_analysis", "address") + .Case("no_sanitize_address", "address") + .Case("no_sanitize_thread", "thread") + .Case("no_sanitize_memory", "memory"); + D->addAttr(::new (S.Context) + NoSanitizeAttr(Attr.getRange(), S.Context, &SanitizerName, 1, + Attr.getAttributeSpellingListIndex())); +} + /// Handles semantic checking for features that are common to all attributes, /// such as checking whether a parameter was properly specified, or the correct /// number of arguments were passed, etc. @@ -4396,6 +4558,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_OptimizeNone: handleOptimizeNoneAttr(S, D, Attr); break; + case AttributeList::AT_FlagEnum: + handleSimpleAttribute<FlagEnumAttr>(S, D, Attr); + break; case AttributeList::AT_Flatten: handleSimpleAttribute<FlattenAttr>(S, D, Attr); break; @@ -4420,8 +4585,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_CUDALaunchBounds: handleLaunchBoundsAttr(S, D, Attr); break; - case AttributeList::AT_Malloc: - handleMallocAttr(S, D, Attr); + case AttributeList::AT_Restrict: + handleRestrictAttr(S, D, Attr); break; case AttributeList::AT_MayAlias: handleSimpleAttribute<MayAliasAttr>(S, D, Attr); @@ -4609,6 +4774,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ObjCNSObject: handleObjCNSObject(S, D, Attr); break; + case AttributeList::AT_ObjCIndependentClass: + handleObjCIndependentClass(S, D, Attr); + break; case AttributeList::AT_Blocks: handleBlocksAttr(S, D, Attr); break; @@ -4645,7 +4813,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_MSABI: case AttributeList::AT_SysVABI: case AttributeList::AT_Pcs: - case AttributeList::AT_PnaclCall: case AttributeList::AT_IntelOclBicc: handleCallConvAttr(S, D, Attr); break; @@ -4657,8 +4824,11 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, break; // Microsoft attributes: - case AttributeList::AT_MsStruct: - handleSimpleAttribute<MsStructAttr>(S, D, Attr); + case AttributeList::AT_MSNoVTable: + handleSimpleAttribute<MSNoVTableAttr>(S, D, Attr); + break; + case AttributeList::AT_MSStruct: + handleSimpleAttribute<MSStructAttr>(S, D, Attr); break; case AttributeList::AT_Uuid: handleUuidAttr(S, D, Attr); @@ -4689,18 +4859,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ScopedLockable: handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr); break; - case AttributeList::AT_NoSanitizeAddress: - handleSimpleAttribute<NoSanitizeAddressAttr>(S, D, Attr); + case AttributeList::AT_NoSanitize: + handleNoSanitizeAttr(S, D, Attr); + break; + case AttributeList::AT_NoSanitizeSpecific: + handleNoSanitizeSpecificAttr(S, D, Attr); break; case AttributeList::AT_NoThreadSafetyAnalysis: handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, Attr); break; - case AttributeList::AT_NoSanitizeThread: - handleSimpleAttribute<NoSanitizeThreadAttr>(S, D, Attr); - break; - case AttributeList::AT_NoSanitizeMemory: - handleSimpleAttribute<NoSanitizeMemoryAttr>(S, D, Attr); - break; case AttributeList::AT_GuardedBy: handleGuardedByAttr(S, D, Attr); break; @@ -4963,8 +5130,7 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { ND = FD; if (ND) { if (IdentifierInfo *Id = ND->getIdentifier()) { - llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I - = WeakUndeclaredIdentifiers.find(Id); + auto I = WeakUndeclaredIdentifiers.find(Id); if (I != WeakUndeclaredIdentifiers.end()) { WeakInfo W = I->second; DeclApplyPragmaWeak(S, ND, W); @@ -5043,7 +5209,8 @@ static bool isDeclDeprecated(Decl *D) { return true; // A category implicitly has the availability of the interface. if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) - return CatD->getClassInterface()->isDeprecated(); + if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface()) + return Interface->isDeprecated(); } while ((D = cast_or_null<Decl>(D->getDeclContext()))); return false; } @@ -5054,12 +5221,13 @@ static bool isDeclUnavailable(Decl *D) { return true; // A category implicitly has the availability of the interface. if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) - return CatD->getClassInterface()->isUnavailable(); + if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface()) + return Interface->isUnavailable(); } while ((D = cast_or_null<Decl>(D->getDeclContext()))); return false; } -static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K, +static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K, Decl *Ctx, const NamedDecl *D, StringRef Message, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass, @@ -5076,8 +5244,8 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K, // Don't warn if our current context is deprecated or unavailable. switch (K) { - case DelayedDiagnostic::Deprecation: - if (isDeclDeprecated(Ctx)) + case Sema::AD_Deprecation: + if (isDeclDeprecated(Ctx) || isDeclUnavailable(Ctx)) return; diag = !ObjCPropertyAccess ? diag::warn_deprecated : diag::warn_property_method_deprecated; @@ -5087,7 +5255,7 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K, available_here_select_kind = /* deprecated */ 2; break; - case DelayedDiagnostic::Unavailable: + case Sema::AD_Unavailable: if (isDeclUnavailable(Ctx)) return; diag = !ObjCPropertyAccess ? diag::err_unavailable @@ -5098,8 +5266,13 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K, available_here_select_kind = /* unavailable */ 0; break; - default: - llvm_unreachable("Neither a deprecation or unavailable kind"); + case Sema::AD_Partial: + diag = diag::warn_partial_availability; + diag_message = diag::warn_partial_message; + diag_fwdclass_message = diag::warn_partial_fwdclass_message; + property_note_select = /* partial */ 2; + available_here_select_kind = /* partial */ 3; + break; } if (!Message.empty()) { @@ -5119,15 +5292,21 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K, S.Diag(D->getLocation(), diag::note_availability_specified_here) << D << available_here_select_kind; + if (K == Sema::AD_Partial) + S.Diag(Loc, diag::note_partial_availability_silence) << D; } static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD, Decl *Ctx) { + assert(DD.Kind == DelayedDiagnostic::Deprecation || + DD.Kind == DelayedDiagnostic::Unavailable); + Sema::AvailabilityDiagnostic AD = DD.Kind == DelayedDiagnostic::Deprecation + ? Sema::AD_Deprecation + : Sema::AD_Unavailable; DD.Triggered = true; - DoEmitAvailabilityWarning(S, (DelayedDiagnostic::DDKind)DD.Kind, Ctx, - DD.getDeprecationDecl(), DD.getDeprecationMessage(), - DD.Loc, DD.getUnknownObjCClass(), - DD.getObjCProperty(), false); + DoEmitAvailabilityWarning( + S, AD, Ctx, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc, + DD.getUnknownObjCClass(), DD.getObjCProperty(), false); } void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { @@ -5193,7 +5372,7 @@ void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD, const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess) { // Delay if we're currently parsing a declaration. - if (DelayedDiagnostics.shouldDelayDiagnostics()) { + if (DelayedDiagnostics.shouldDelayDiagnostics() && AD != AD_Partial) { DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability( AD, Loc, D, UnknownObjCClass, ObjCProperty, Message, ObjCPropertyAccess)); @@ -5201,16 +5380,6 @@ void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD, } Decl *Ctx = cast<Decl>(getCurLexicalContext()); - DelayedDiagnostic::DDKind K; - switch (AD) { - case AD_Deprecation: - K = DelayedDiagnostic::Deprecation; - break; - case AD_Unavailable: - K = DelayedDiagnostic::Unavailable; - break; - } - - DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc, - UnknownObjCClass, ObjCProperty, ObjCPropertyAccess); + DoEmitAvailabilityWarning(*this, AD, Ctx, D, Message, Loc, UnknownObjCClass, + ObjCProperty, ObjCPropertyAccess); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index 510738e..b1dfe0e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -316,8 +316,17 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) { Param->setInvalidDecl(); return; - } - + } + + // C++11 [dcl.fct.default]p3 + // A default argument expression [...] shall not be specified for a + // parameter pack. + if (Param->isParameterPack()) { + Diag(EqualLoc, diag::err_param_default_argument_on_parameter_pack) + << DefaultArg->getSourceRange(); + return; + } + // Check that the default argument is well-formed CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this); if (DefaultArgChecker.Visit(DefaultArg)) { @@ -429,6 +438,45 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S) { bool Invalid = false; + // The declaration context corresponding to the scope is the semantic + // parent, unless this is a local function declaration, in which case + // it is that surrounding function. + DeclContext *ScopeDC = New->isLocalExternDecl() + ? New->getLexicalDeclContext() + : New->getDeclContext(); + + // Find the previous declaration for the purpose of default arguments. + FunctionDecl *PrevForDefaultArgs = Old; + for (/**/; PrevForDefaultArgs; + // Don't bother looking back past the latest decl if this is a local + // extern declaration; nothing else could work. + PrevForDefaultArgs = New->isLocalExternDecl() + ? nullptr + : PrevForDefaultArgs->getPreviousDecl()) { + // Ignore hidden declarations. + if (!LookupResult::isVisible(*this, PrevForDefaultArgs)) + continue; + + if (S && !isDeclInScope(PrevForDefaultArgs, ScopeDC, S) && + !New->isCXXClassMember()) { + // Ignore default arguments of old decl if they are not in + // the same scope and this is not an out-of-line definition of + // a member function. + continue; + } + + if (PrevForDefaultArgs->isLocalExternDecl() != New->isLocalExternDecl()) { + // If only one of these is a local function declaration, then they are + // declared in different scopes, even though isDeclInScope may think + // they're in the same scope. (If both are local, the scope check is + // sufficent, and if neither is local, then they are in the same scope.) + continue; + } + + // We found our guy. + break; + } + // C++ [dcl.fct.default]p4: // For non-template functions, default arguments can be added in // later declarations of a function in the same @@ -447,34 +495,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // in a member function definition that appears outside of the class // definition are added to the set of default arguments provided by the // member function declaration in the class definition. - for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) { - ParmVarDecl *OldParam = Old->getParamDecl(p); + for (unsigned p = 0, NumParams = PrevForDefaultArgs + ? PrevForDefaultArgs->getNumParams() + : 0; + p < NumParams; ++p) { + ParmVarDecl *OldParam = PrevForDefaultArgs->getParamDecl(p); ParmVarDecl *NewParam = New->getParamDecl(p); - bool OldParamHasDfl = OldParam->hasDefaultArg(); + bool OldParamHasDfl = OldParam ? OldParam->hasDefaultArg() : false; bool NewParamHasDfl = NewParam->hasDefaultArg(); - // The declaration context corresponding to the scope is the semantic - // parent, unless this is a local function declaration, in which case - // it is that surrounding function. - DeclContext *ScopeDC = New->isLocalExternDecl() - ? New->getLexicalDeclContext() - : New->getDeclContext(); - if (S && !isDeclInScope(Old, ScopeDC, S) && - !New->getDeclContext()->isRecord()) - // Ignore default parameters of old decl if they are not in - // the same scope and this is not an out-of-line definition of - // a member function. - OldParamHasDfl = false; - if (New->isLocalExternDecl() != Old->isLocalExternDecl()) - // If only one of these is a local function declaration, then they are - // declared in different scopes, even though isDeclInScope may think - // they're in the same scope. (If both are local, the scope check is - // sufficent, and if neither is local, then they are in the same scope.) - OldParamHasDfl = false; - if (OldParamHasDfl && NewParamHasDfl) { - unsigned DiagDefaultParamID = diag::err_param_default_argument_redefinition; @@ -482,7 +513,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // of template class. The new default parameter's value is ignored. Invalid = true; if (getLangOpts().MicrosoftExt) { - CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(New); + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(New); if (MD && MD->getParent()->getDescribedClassTemplate()) { // Merge the old default argument into the new parameter. NewParam->setHasInheritedDefaultArg(); @@ -509,14 +540,12 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // Look for the function declaration where the default argument was // actually written, which may be a declaration prior to Old. - for (FunctionDecl *Older = Old->getPreviousDecl(); - Older; Older = Older->getPreviousDecl()) { - if (!Older->getParamDecl(p)->hasDefaultArg()) - break; - + for (auto Older = PrevForDefaultArgs; + OldParam->hasInheritedDefaultArg(); /**/) { + Older = Older->getPreviousDecl(); OldParam = Older->getParamDecl(p); - } - + } + Diag(OldParam->getLocation(), diag::note_previous_definition) << OldParam->getDefaultArgRange(); } else if (OldParamHasDfl) { @@ -524,7 +553,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // It's important to use getInit() here; getDefaultArg() // strips off any top-level ExprWithCleanups. NewParam->setHasInheritedDefaultArg(); - if (OldParam->hasUninstantiatedDefaultArg()) + if (OldParam->hasUnparsedDefaultArg()) + NewParam->setUnparsedDefaultArg(); + else if (OldParam->hasUninstantiatedDefaultArg()) NewParam->setUninstantiatedDefaultArg( OldParam->getUninstantiatedDefaultArg()); else @@ -535,8 +566,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Diag(NewParam->getLocation(), diag::err_param_default_argument_template_redecl) << NewParam->getDefaultArgRange(); - Diag(Old->getLocation(), diag::note_template_prev_declaration) - << false; + Diag(PrevForDefaultArgs->getLocation(), + diag::note_template_prev_declaration) + << false; } else if (New->getTemplateSpecializationKind() != TSK_ImplicitInstantiation && New->getTemplateSpecializationKind() != TSK_Undeclared) { @@ -607,7 +639,8 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, << New << New->isConstexpr(); Diag(Old->getLocation(), diag::note_previous_declaration); Invalid = true; - } else if (!Old->isInlined() && New->isInlined() && Old->isDefined(Def)) { + } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() && + Old->isDefined(Def)) { // C++11 [dcl.fcn.spec]p4: // If the definition of a function appears in a translation unit before its // first declaration as inline, the program is ill-formed. @@ -689,16 +722,16 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { break; } - // C++ [dcl.fct.default]p4: - // In a given function declaration, all parameters - // subsequent to a parameter with a default argument shall - // have default arguments supplied in this or previous - // declarations. A default argument shall not be redefined - // by a later declaration (not even to the same value). + // C++11 [dcl.fct.default]p4: + // In a given function declaration, each parameter subsequent to a parameter + // with a default argument shall have a default argument supplied in this or + // a previous declaration or shall be a function parameter pack. A default + // argument shall not be redefined by a later declaration (not even to the + // same value). unsigned LastMissingDefaultArg = 0; for (; p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); - if (!Param->hasDefaultArg()) { + if (!Param->hasDefaultArg() && !Param->isParameterPack()) { if (Param->isInvalidDecl()) /* We already complained about this parameter. */; else if (Param->getIdentifier()) @@ -795,7 +828,8 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { // - it shall not be virtual; const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD); if (Method && Method->isVirtual()) { - Diag(NewFD->getLocation(), diag::err_constexpr_virtual); + Method = Method->getCanonicalDecl(); + Diag(Method->getLocation(), diag::err_constexpr_virtual); // If it's not obvious why this function is virtual, find an overridden // function which uses the 'virtual' keyword. @@ -1545,6 +1579,31 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, return true; } +/// Use small set to collect indirect bases. As this is only used +/// locally, there's no need to abstract the small size parameter. +typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet; + +/// \brief Recursively add the bases of Type. Don't add Type itself. +static void +NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, + const QualType &Type) +{ + // Even though the incoming type is a base, it might not be + // a class -- it could be a template parm, for instance. + if (auto Rec = Type->getAs<RecordType>()) { + auto Decl = Rec->getAsCXXRecordDecl(); + + // Iterate over its bases. + for (const auto &BaseSpec : Decl->bases()) { + QualType Base = Context.getCanonicalType(BaseSpec.getType()) + .getUnqualifiedType(); + if (Set.insert(Base).second) + // If we've not already seen it, recurse. + NoteIndirectBases(Context, Set, Base); + } + } +} + /// \brief Performs the actual work of attaching the given base class /// specifiers to a C++ class. bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, @@ -1558,6 +1617,10 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // class. std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes; + // Used to track indirect bases so we can see if a direct base is + // ambiguous. + IndirectBaseSet IndirectBaseTypes; + // Copy non-redundant base specifiers into permanent storage. unsigned NumGoodBases = 0; bool Invalid = false; @@ -1585,6 +1648,11 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // Okay, add this new base class. KnownBase = Bases[idx]; Bases[NumGoodBases++] = Bases[idx]; + + // Note this base's direct & indirect bases, if there could be ambiguity. + if (NumBases > 1) + NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType); + if (const RecordType *Record = NewBaseType->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); if (Class->isInterface() && @@ -1605,11 +1673,33 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // Attach the remaining base class specifiers to the derived class. Class->setBases(Bases, NumGoodBases); + + for (unsigned idx = 0; idx < NumGoodBases; ++idx) { + // Check whether this direct base is inaccessible due to ambiguity. + QualType BaseType = Bases[idx]->getType(); + CanQualType CanonicalBase = Context.getCanonicalType(BaseType) + .getUnqualifiedType(); + + if (IndirectBaseTypes.count(CanonicalBase)) { + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + bool found + = Class->isDerivedFrom(CanonicalBase->getAsCXXRecordDecl(), Paths); + assert(found); + (void)found; + + if (Paths.isAmbiguous(CanonicalBase)) + Diag(Bases[idx]->getLocStart (), diag::warn_inaccessible_base_class) + << BaseType << getAmbiguousPathsDisplayString(Paths) + << Bases[idx]->getSourceRange(); + else + assert(Bases[idx]->isVirtual()); + } - // Delete the remaining (good) base class specifiers, since their - // data has been copied into the CXXRecordDecl. - for (unsigned idx = 0; idx < NumGoodBases; ++idx) + // Delete the base class specifier, since its data has been copied + // into the CXXRecordDecl. Context.Deallocate(Bases[idx]); + } return Invalid; } @@ -1689,18 +1779,6 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths, BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base)); } -/// \brief Determine whether the given base path includes a virtual -/// base class. -bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) { - for (CXXCastPath::const_iterator B = BasePath.begin(), - BEnd = BasePath.end(); - B != BEnd; ++B) - if ((*B)->isVirtual()) - return true; - - return false; -} - /// CheckDerivedToBaseConversion - Check whether the Derived-to-Base /// conversion (where Derived and Base are class types) is /// well-formed, meaning that the conversion is unambiguous (and @@ -2159,7 +2237,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, assert(Member && "HandleField never returns null"); } } else { - assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static); + assert(InitStyle == ICIS_NoInit || + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static); Member = HandleDeclarator(S, D, TemplateParameterLists); if (!Member) @@ -3537,8 +3616,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation()); Expr *CtorArgE = CtorArg.getAs<Expr>(); - InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, CtorArgE); - + InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, + CtorArgE); + ExprResult MemberInit = InitSeq.Perform(SemaRef, Entities.back(), InitKind, MultiExprArg(&CtorArgE, 1)); @@ -4659,15 +4739,15 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info, } /// \brief Check class-level dllimport/dllexport attribute. -static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) { +void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); // MSVC inherits DLL attributes to partial class template specializations. - if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) { + if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) { if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) { if (Attr *TemplateAttr = getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) { - auto *A = cast<InheritableAttr>(TemplateAttr->clone(S.getASTContext())); + auto *A = cast<InheritableAttr>(TemplateAttr->clone(getASTContext())); A->setInherited(true); ClassAttr = A; } @@ -4678,12 +4758,12 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) { return; if (!Class->isExternallyVisible()) { - S.Diag(Class->getLocation(), diag::err_attribute_dll_not_extern) + Diag(Class->getLocation(), diag::err_attribute_dll_not_extern) << Class << ClassAttr; return; } - if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && + if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr->isInherited()) { // Diagnose dll attributes on members of class with dll attribute. for (Decl *Member : Class->decls()) { @@ -4693,10 +4773,10 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) { if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl()) continue; - S.Diag(MemberAttr->getLocation(), + Diag(MemberAttr->getLocation(), diag::err_attribute_dll_member_of_dll_class) << MemberAttr << ClassAttr; - S.Diag(ClassAttr->getLocation(), diag::note_previous_attribute); + Diag(ClassAttr->getLocation(), diag::note_previous_attribute); Member->setInvalidDecl(); } } @@ -4709,15 +4789,20 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) { const bool ClassExported = ClassAttr->getKind() == attr::DLLExport; const bool ClassImported = !ClassExported; + TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); + + // Don't dllexport explicit class template instantiation declarations. + if (ClassExported && TSK == TSK_ExplicitInstantiationDeclaration) { + Class->dropAttr<DLLExportAttr>(); + return; + } + // Force declaration of implicit members so they can inherit the attribute. - S.ForceDeclarationOfImplicitMembers(Class); + ForceDeclarationOfImplicitMembers(Class); // FIXME: MSVC's docs say all bases must be exportable, but this doesn't // seem to be true in practice? - TemplateSpecializationKind TSK = - Class->getTemplateSpecializationKind(); - for (Decl *Member : Class->decls()) { VarDecl *VD = dyn_cast<VarDecl>(Member); CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member); @@ -4731,22 +4816,25 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) { if (MD->isDeleted()) continue; - if (MD->isMoveAssignmentOperator() && ClassImported && MD->isInlined()) { - // Current MSVC versions don't export the move assignment operators, so - // don't attempt to import them if we have a definition. - continue; - } + if (MD->isInlined()) { + // MinGW does not import or export inline methods. + if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) + continue; - if (MD->isInlined() && ClassImported && - !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { - // MinGW does not import inline functions. - continue; + // MSVC versions before 2015 don't export the move assignment operators, + // so don't attempt to import them if we have a definition. + if (ClassImported && MD->isMoveAssignmentOperator() && + !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015)) + continue; } } + if (!cast<NamedDecl>(Member)->isExternallyVisible()) + continue; + if (!getDLLAttr(Member)) { auto *NewAttr = - cast<InheritableAttr>(ClassAttr->clone(S.getASTContext())); + cast<InheritableAttr>(ClassAttr->clone(getASTContext())); NewAttr->setInherited(true); Member->addAttr(NewAttr); } @@ -4761,7 +4849,7 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) { if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) continue; - S.MarkFunctionReferenced(Class->getLocation(), MD); + MarkFunctionReferenced(Class->getLocation(), MD); // The function will be passed to the consumer when its definition is // encountered. @@ -4772,11 +4860,17 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) { // defaulted methods, and the copy and move assignment operators. The // latter are exported even if they are trivial, because the address of // an operator can be taken and should compare equal accross libraries. - S.MarkFunctionReferenced(Class->getLocation(), MD); + DiagnosticErrorTrap Trap(Diags); + MarkFunctionReferenced(Class->getLocation(), MD); + if (Trap.hasErrorOccurred()) { + Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class) + << Class->getName() << !getLangOpts().CPlusPlus11; + break; + } // There is no later point when we will see the definition of this // function, so pass it to the consumer now. - S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); + Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); } } } @@ -4820,9 +4914,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } - if (Record->isDynamicClass() && !Record->isDependentType()) - DynamicClasses.push_back(Record); - if (Record->getIdentifier()) { // C++ [class.mem]p13: // If T is the name of a class, then each of the following shall have a @@ -4923,7 +5014,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // have inheriting constructors. DeclareInheritingConstructors(Record); - checkDLLAttribute(*this, Record); + checkClassLevelDLLAttribute(Record); } /// Look up the special member function that would be called by a special @@ -7318,7 +7409,7 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { StdInitializerList = Template; } - if (Template != StdInitializerList) + if (Template->getCanonicalDecl() != StdInitializerList->getCanonicalDecl()) return false; // This is an instance of std::initializer_list. Find the argument type. @@ -8029,15 +8120,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, if (RequireCompleteDeclContext(SS, LookupContext)) return BuildInvalid(); - // The normal rules do not apply to inheriting constructor declarations. - if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { - UsingDecl *UD = BuildValid(); - CheckInheritingConstructorUsingDecl(UD); - return UD; - } - - // Otherwise, look up the target name. - + // Look up the target name. LookupResult R(*this, NameInfo, LookupOrdinaryName); // Unlike most lookups, we don't always want to hide tag @@ -8056,8 +8139,12 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, LookupQualifiedName(R, LookupContext); - // Try to correct typos if possible. - if (R.empty()) { + // Try to correct typos if possible. If constructor name lookup finds no + // results, that means the named class has no explicit constructors, and we + // suppressed declaring implicit ones (probably because it's dependent or + // invalid). + if (R.empty() && + NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) { if (TypoCorrection Corrected = CorrectTypo( R.getLookupNameInfo(), R.getLookupKind(), S, &SS, llvm::make_unique<UsingValidatorCCC>( @@ -8087,16 +8174,12 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(Context.getRecordType(RD)))); NameInfo.setNamedTypeInfo(nullptr); - - // Build it and process it as an inheriting constructor. - UsingDecl *UD = BuildValid(); - CheckInheritingConstructorUsingDecl(UD); - return UD; + for (auto *Ctor : LookupConstructors(RD)) + R.addDecl(Ctor); + } else { + // FIXME: Pick up all the declarations if we found an overloaded function. + R.addDecl(ND); } - - // FIXME: Pick up all the declarations if we found an overloaded function. - R.setLookupName(Corrected.getCorrection()); - R.addDecl(ND); } else { Diag(IdentLoc, diag::err_no_member) << NameInfo.getName() << LookupContext << SS.getRange(); @@ -8136,6 +8219,18 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } UsingDecl *UD = BuildValid(); + + // The normal rules do not apply to inheriting constructor declarations. + if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { + // Suppress access diagnostics; the access check is instead performed at the + // point of use for an inheriting constructor. + R.suppressDiagnostics(); + CheckInheritingConstructorUsingDecl(UD); + return UD; + } + + // Otherwise, look up the target name. + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { UsingShadowDecl *PrevDecl = nullptr; if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl)) @@ -8421,7 +8516,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, SourceLocation UsingLoc, UnqualifiedId &Name, AttributeList *AttrList, - TypeResult Type) { + TypeResult Type, + Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. while (S->getFlags() & Scope::TemplateParamScope) S = S->getParent(); @@ -8549,6 +8645,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, NewND = NewDecl; } else { + if (auto *TD = dyn_cast_or_null<TagDecl>(DeclFromDeclSpec)) { + setTagNameForLinkagePurposes(TD, NewTD); + handleTagNumbering(TD, S); + } ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); NewND = NewTD; } @@ -9014,7 +9114,7 @@ private: ASTContext &Context = SemaRef.Context; DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(Context.getRecordType(Base))); - DeclContext::lookup_const_result Decls = Derived->lookup(Name); + DeclContext::lookup_result Decls = Derived->lookup(Name); return Decls.empty() ? Derived->getLocation() : Decls[0]->getLocation(); } @@ -9363,6 +9463,44 @@ void Sema::ActOnFinishCXXMemberDecls() { } } +static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) { + // Don't do anything for template patterns. + if (Class->getDescribedClassTemplate()) + return; + + for (Decl *Member : Class->decls()) { + auto *CD = dyn_cast<CXXConstructorDecl>(Member); + if (!CD) { + // Recurse on nested classes. + if (auto *NestedRD = dyn_cast<CXXRecordDecl>(Member)) + getDefaultArgExprsForConstructors(S, NestedRD); + continue; + } else if (!CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) { + continue; + } + + for (unsigned I = 0, E = CD->getNumParams(); I != E; ++I) { + // Skip any default arguments that we've already instantiated. + if (S.Context.getDefaultArgExprForConstructor(CD, I)) + continue; + + Expr *DefaultArg = S.BuildCXXDefaultArgExpr(Class->getLocation(), CD, + CD->getParamDecl(I)).get(); + S.Context.addDefaultArgExprForConstructor(CD, I, DefaultArg); + } + } +} + +void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) { + auto *RD = dyn_cast<CXXRecordDecl>(D); + + // Default constructors that are annotated with __declspec(dllexport) which + // have default arguments or don't use the standard calling convention are + // wrapped with a thunk called the default constructor closure. + if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft()) + getDefaultArgExprsForConstructors(*this, RD); +} + void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, CXXDestructorDecl *Destructor) { assert(getLangOpts().CPlusPlus11 && @@ -9397,8 +9535,8 @@ namespace { // copy/move operators. These classes serve as factory functions and help us // avoid using the same Expr* in the AST twice. class ExprBuilder { - ExprBuilder(const ExprBuilder&) LLVM_DELETED_FUNCTION; - ExprBuilder &operator=(const ExprBuilder&) LLVM_DELETED_FUNCTION; + ExprBuilder(const ExprBuilder&) = delete; + ExprBuilder &operator=(const ExprBuilder&) = delete; protected: static Expr *assertNotNull(Expr *E) { @@ -10101,7 +10239,9 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Assign non-static members. for (auto *Field : ClassDecl->fields()) { - if (Field->isUnnamedBitfield()) + // FIXME: We should form some kind of AST representation for the implied + // memcpy in a union copy operation. + if (Field->isUnnamedBitfield() || Field->getParent()->isUnion()) continue; if (Field->isInvalidDecl()) { @@ -10531,7 +10671,9 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // Assign non-static members. for (auto *Field : ClassDecl->fields()) { - if (Field->isUnnamedBitfield()) + // FIXME: We should form some kind of AST representation for the implied + // memcpy in a union copy operation. + if (Field->isUnnamedBitfield() || Field->getParent()->isUnion()) continue; if (Field->isInvalidDecl()) { @@ -11881,7 +12023,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, // // We just pretend to initialize the object with itself, then make sure // it can be destroyed later. - QualType initType = ExDeclType; + QualType initType = Context.getExceptionObjectType(ExDeclType); InitializedEntity entity = InitializedEntity::InitializeVariable(ExDecl); @@ -13122,7 +13264,8 @@ bool Sema::DefineUsedVTables() { DefinedAnything = true; MarkVirtualMembersReferenced(Loc, Class); CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl()); - Consumer.HandleVTable(Class, VTablesUsed[Canonical]); + if (VTablesUsed[Canonical]) + Consumer.HandleVTable(Class); // Optionally warn if we're emitting a weak vtable. if (Class->isExternallyVisible() && diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index 7e3da94..3831879 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -448,6 +448,19 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { } +static void diagnoseUseOfProtocols(Sema &TheSema, + ObjCContainerDecl *CD, + ObjCProtocolDecl *const *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs) { + assert(ProtoRefs); + // Diagnose availability in the context of the ObjC container. + Sema::ContextRAII SavedContext(TheSema, CD); + for (unsigned i = 0; i < NumProtoRefs; ++i) { + (void)TheSema.DiagnoseUseOfDecl(ProtoRefs[i], ProtoLocs[i]); + } +} + Decl *Sema:: ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, @@ -535,6 +548,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *SuperClassDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + // Diagnose availability in the context of the @interface. + ContextRAII SavedContext(*this, IDecl); // Diagnose classes that inherit from deprecated classes. if (SuperClassDecl) (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); @@ -591,6 +606,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, // Check then save referenced protocols. if (NumProtoRefs) { + diagnoseUseOfProtocols(*this, IDecl, (ObjCProtocolDecl*const*)ProtoRefs, + NumProtoRefs, ProtoLocs); IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); IDecl->setEndOfDefinitionLoc(EndProtoLoc); @@ -617,8 +634,7 @@ void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs, QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) - for (auto *I : OPT->quals()) - ProtocolRefs.push_back(I); + ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end()); } } @@ -752,6 +768,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, if (!err && NumProtoRefs ) { /// Check then save referenced protocols. + diagnoseUseOfProtocols(*this, PDecl, (ObjCProtocolDecl*const*)ProtoRefs, + NumProtoRefs, ProtoLocs); PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); } @@ -779,7 +797,7 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl, /// issues an error if they are not declared. It returns list of /// protocol declarations in its 'Protocols' argument. void -Sema::FindProtocolDeclaration(bool WarnOnDeclarations, +Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, const IdentifierLocPair *ProtocolId, unsigned NumProtocols, SmallVectorImpl<Decl *> &Protocols) { @@ -805,8 +823,12 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, // If this is a forward protocol declaration, get its definition. if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition()) PDecl = PDecl->getDefinition(); - - (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second); + + // For an objc container, delay protocol reference checking until after we + // can set the objc decl as the availability context, otherwise check now. + if (!ForObjCContainer) { + (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second); + } // If this is a forward declaration and we are supposed to warn in this // case, do it. @@ -935,7 +957,9 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, CurContext->addDecl(CDecl); if (NumProtoRefs) { - CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, + diagnoseUseOfProtocols(*this, CDecl, (ObjCProtocolDecl*const*)ProtoRefs, + NumProtoRefs, ProtoLocs); + CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); // Protocols in the class extension belong to the class. if (CDecl->IsClassExtension()) @@ -2241,8 +2265,14 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty()) continue; - if (!MatchTwoMethodDeclarations(Method, List->getMethod())) + if (!MatchTwoMethodDeclarations(Method, List->getMethod())) { + // Even if two method types do not match, we would like to say + // there is more than one declaration so unavailability/deprecated + // warning is not too noisy. + if (!Method->isDefined()) + List->setHasMoreThanOneDecl(true); continue; + } ObjCMethodDecl *PrevObjCMethod = List->getMethod(); @@ -2341,19 +2371,33 @@ bool Sema::CollectMultipleMethodsInGlobalPool( return Methods.size() > 1; } -bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, bool instance) { +bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod, + SourceRange R, + bool receiverIdOrClass) { GlobalMethodPool::iterator Pos = MethodPool.find(Sel); // Test for no method in the pool which should not trigger any warning by // caller. if (Pos == MethodPool.end()) return true; - ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; + ObjCMethodList &MethList = + BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second; + + // Diagnose finding more than one method in global pool + SmallVector<ObjCMethodDecl *, 4> Methods; + Methods.push_back(BestMethod); + for (ObjCMethodList *ML = &MethList; ML; ML = ML->getNext()) + if (ObjCMethodDecl *M = ML->getMethod()) + if (!M->isHidden() && M != BestMethod && !M->hasAttr<UnavailableAttr>()) + Methods.push_back(M); + if (Methods.size() > 1) + DiagnoseMultipleMethodInGlobalPool(Methods, Sel, R, receiverIdOrClass); + return MethList.hasMoreThanOneDecl(); } ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, bool receiverIdOrClass, - bool warn, bool instance) { + bool instance) { if (ExternalSource) ReadMethodPool(Sel); @@ -2365,31 +2409,23 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; SmallVector<ObjCMethodDecl *, 4> Methods; for (ObjCMethodList *M = &MethList; M; M = M->getNext()) { - if (M->getMethod() && !M->getMethod()->isHidden()) { - // If we're not supposed to warn about mismatches, we're done. - if (!warn) - return M->getMethod(); - - Methods.push_back(M->getMethod()); - } + if (M->getMethod() && !M->getMethod()->isHidden()) + return M->getMethod(); } + return nullptr; +} - // If there aren't any visible methods, we're done. - // FIXME: Recover if there are any known-but-hidden methods? - if (Methods.empty()) - return nullptr; - - if (Methods.size() == 1) - return Methods[0]; - +void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods, + Selector Sel, SourceRange R, + bool receiverIdOrClass) { // We found multiple methods, so we may have to complain. bool issueDiagnostic = false, issueError = false; // We support a warning which complains about *any* difference in // method signature. bool strictSelectorMatch = - receiverIdOrClass && warn && - !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin()); + receiverIdOrClass && + !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin()); if (strictSelectorMatch) { for (unsigned I = 1, N = Methods.size(); I != N; ++I) { if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) { @@ -2414,7 +2450,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, break; } } - + if (issueDiagnostic) { if (issueError) Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R; @@ -2422,16 +2458,15 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R; else Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - + Diag(Methods[0]->getLocStart(), issueError ? diag::note_possibility : diag::note_using) - << Methods[0]->getSourceRange(); + << Methods[0]->getSourceRange(); for (unsigned I = 1, N = Methods.size(); I != N; ++I) { Diag(Methods[I]->getLocStart(), diag::note_also_found) - << Methods[I]->getSourceRange(); - } + << Methods[I]->getSourceRange(); + } } - return Methods[0]; } ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { @@ -2442,12 +2477,16 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { GlobalMethods &Methods = Pos->second; for (const ObjCMethodList *Method = &Methods.first; Method; Method = Method->getNext()) - if (Method->getMethod() && Method->getMethod()->isDefined()) + if (Method->getMethod() && + (Method->getMethod()->isDefined() || + Method->getMethod()->isPropertyAccessor())) return Method->getMethod(); for (const ObjCMethodList *Method = &Methods.second; Method; Method = Method->getNext()) - if (Method->getMethod() && Method->getMethod()->isDefined()) + if (Method->getMethod() && + (Method->getMethod()->isDefined() || + Method->getMethod()->isPropertyAccessor())) return Method->getMethod(); return nullptr; } @@ -2571,10 +2610,9 @@ Sema::ObjCContainerKind Sema::getObjCContainerKind() const { case Decl::ObjCProtocol: return Sema::OCK_Protocol; case Decl::ObjCCategory: - if (dyn_cast<ObjCCategoryDecl>(CurContext)->IsClassExtension()) + if (cast<ObjCCategoryDecl>(CurContext)->IsClassExtension()) return Sema::OCK_ClassExtension; - else - return Sema::OCK_Category; + return Sema::OCK_Category; case Decl::ObjCImplementation: return Sema::OCK_Implementation; case Decl::ObjCCategoryImpl: @@ -3286,7 +3324,7 @@ Decl *Sema::ActOnMethodDeclaration( case OMF_alloc: case OMF_new: - InferRelatedResultType = ObjCMethod->isClassMethod(); + InferRelatedResultType = ObjCMethod->isClassMethod(); break; case OMF_init: @@ -3297,7 +3335,8 @@ Decl *Sema::ActOnMethodDeclaration( break; } - if (InferRelatedResultType) + if (InferRelatedResultType && + !ObjCMethod->getReturnType()->isObjCIndependentClassType()) ObjCMethod->SetRelatedResultType(); } @@ -3487,12 +3526,11 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { if (ReferencedSelectors.empty() || !Context.AnyObjCImplementation()) return; - for (llvm::DenseMap<Selector, SourceLocation>::iterator S = - ReferencedSelectors.begin(), - E = ReferencedSelectors.end(); S != E; ++S) { - Selector Sel = (*S).first; + for (auto &SelectorAndLocation : ReferencedSelectors) { + Selector Sel = SelectorAndLocation.first; + SourceLocation Loc = SelectorAndLocation.second; if (!LookupImplementedMethodInGlobalPool(Sel)) - Diag((*S).second, diag::warn_unimplemented_selector) << Sel; + Diag(Loc, diag::warn_unimplemented_selector) << Sel; } return; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp index 2387325..51d6ace 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -167,13 +167,13 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { void Sema::UpdateExceptionSpec(FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI) { - for (auto *Redecl : FD->redecls()) - Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI); - // If we've fully resolved the exception specification, notify listeners. if (!isUnresolvedExceptionSpec(ESI.Type)) if (auto *Listener = getASTMutationListener()) Listener->ResolvedExceptionSpec(FD); + + for (auto *Redecl : FD->redecls()) + Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI); } /// Determine whether a function has an implicitly-generated exception @@ -437,7 +437,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, OldNR != FunctionProtoType::NR_NoNoexcept && NewNR != FunctionProtoType::NR_NoNoexcept) { Diag(NewLoc, DiagID); - if (NoteID.getDiagID() != 0) + if (NoteID.getDiagID() != 0 && OldLoc.isValid()) Diag(OldLoc, NoteID); return true; } @@ -518,7 +518,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, } Diag(NewLoc, DiagID); - if (NoteID.getDiagID() != 0) + if (NoteID.getDiagID() != 0 && OldLoc.isValid()) Diag(OldLoc, NoteID); return true; } @@ -547,7 +547,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, return false; } Diag(NewLoc, DiagID); - if (NoteID.getDiagID() != 0) + if (NoteID.getDiagID() != 0 && OldLoc.isValid()) Diag(OldLoc, NoteID); return true; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 8be1157..7ab269c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -76,25 +76,57 @@ bool Sema::CanUseDecl(NamedDecl *D) { static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { // Warn if this is used but marked unused. if (D->hasAttr<UnusedAttr>()) { - const Decl *DC = cast<Decl>(S.getCurObjCLexicalContext()); - if (!DC->hasAttr<UnusedAttr>()) + const Decl *DC = cast_or_null<Decl>(S.getCurObjCLexicalContext()); + if (DC && !DC->hasAttr<UnusedAttr>()) S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); } } -static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, - NamedDecl *D, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass, - bool ObjCPropertyAccess) { +static bool HasRedeclarationWithoutAvailabilityInCategory(const Decl *D) { + const auto *OMD = dyn_cast<ObjCMethodDecl>(D); + if (!OMD) + return false; + const ObjCInterfaceDecl *OID = OMD->getClassInterface(); + if (!OID) + return false; + + for (const ObjCCategoryDecl *Cat : OID->visible_categories()) + if (ObjCMethodDecl *CatMeth = + Cat->getMethod(OMD->getSelector(), OMD->isInstanceMethod())) + if (!CatMeth->hasAttr<AvailabilityAttr>()) + return true; + return false; +} + +static AvailabilityResult +DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass, + bool ObjCPropertyAccess) { // See if this declaration is unavailable or deprecated. std::string Message; + AvailabilityResult Result = D->getAvailability(&Message); + + // For typedefs, if the typedef declaration appears available look + // to the underlying type to see if it is more restrictive. + while (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { + if (Result == AR_Available) { + if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) { + D = TT->getDecl(); + Result = D->getAvailability(&Message); + continue; + } + } + break; + } // Forward class declarations get their attributes from their definition. if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) { - if (IDecl->getDefinition()) + if (IDecl->getDefinition()) { D = IDecl->getDefinition(); + Result = D->getAvailability(&Message); + } } - AvailabilityResult Result = D->getAvailability(&Message); + if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) if (Result == AR_Available) { const DeclContext *DC = ECD->getDeclContext(); @@ -103,7 +135,8 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, } const ObjCPropertyDecl *ObjCPDecl = nullptr; - if (Result == AR_Deprecated || Result == AR_Unavailable) { + if (Result == AR_Deprecated || Result == AR_Unavailable || + AR_NotYetIntroduced) { if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) { AvailabilityResult PDeclResult = PD->getAvailability(nullptr); @@ -115,7 +148,6 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, switch (Result) { case AR_Available: - case AR_NotYetIntroduced: break; case AR_Deprecated: @@ -125,6 +157,34 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, ObjCPropertyAccess); break; + case AR_NotYetIntroduced: { + // Don't do this for enums, they can't be redeclared. + if (isa<EnumConstantDecl>(D) || isa<EnumDecl>(D)) + break; + + bool Warn = !D->getAttr<AvailabilityAttr>()->isInherited(); + // Objective-C method declarations in categories are not modelled as + // redeclarations, so manually look for a redeclaration in a category + // if necessary. + if (Warn && HasRedeclarationWithoutAvailabilityInCategory(D)) + Warn = false; + // In general, D will point to the most recent redeclaration. However, + // for `@class A;` decls, this isn't true -- manually go through the + // redecl chain in that case. + if (Warn && isa<ObjCInterfaceDecl>(D)) + for (Decl *Redecl = D->getMostRecentDecl(); Redecl && Warn; + Redecl = Redecl->getPreviousDecl()) + if (!Redecl->hasAttr<AvailabilityAttr>() || + Redecl->getAttr<AvailabilityAttr>()->isInherited()) + Warn = false; + + if (Warn) + S.EmitAvailabilityWarning(Sema::AD_Partial, D, Message, Loc, + UnknownObjCClass, ObjCPDecl, + ObjCPropertyAccess); + break; + } + case AR_Unavailable: if (S.getCurContextAvailability() != AR_Unavailable) S.EmitAvailabilityWarning(Sema::AD_Unavailable, @@ -307,7 +367,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, DeduceReturnType(FD, Loc)) return true; } - DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, ObjCPropertyAccess); + DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, + ObjCPropertyAccess); DiagnoseUnusedOfDecl(*this, D, Loc); @@ -405,12 +466,11 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, SourceLocation MissingNilLoc = PP.getLocForEndOfToken(sentinelExpr->getLocEnd()); std::string NullValue; - if (calleeType == CT_Method && - PP.getIdentifierInfo("nil")->hasMacroDefinition()) + if (calleeType == CT_Method && PP.isMacroDefined("nil")) NullValue = "nil"; else if (getLangOpts().CPlusPlus11) NullValue = "nullptr"; - else if (PP.getIdentifierInfo("NULL")->hasMacroDefinition()) + else if (PP.isMacroDefined("NULL")) NullValue = "NULL"; else NullValue = "(void*) 0"; @@ -3266,7 +3326,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { if (Ty == Context.DoubleTy) { if (getLangOpts().SinglePrecisionConstants) { Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); - } else if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp64) { + } else if (getLangOpts().OpenCL && + !((getLangOpts().OpenCLVersion >= 120) || + getOpenCLOptions().cl_khr_fp64)) { Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64); Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); } @@ -3322,6 +3384,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { Diag(Tok.getLocation(), diag::err_int128_unsupported); Width = MaxWidth; Ty = Context.getIntMaxType(); + } else if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) { + Width = 8; + Ty = Context.CharTy; } else { Width = Literal.MicrosoftInteger; Ty = Context.getIntTypeForBitwidth(Width, @@ -4558,6 +4623,83 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) { return hasInvalid; } +/// If a builtin function has a pointer argument with no explicit address +/// space, than it should be able to accept a pointer to any address +/// space as input. In order to do this, we need to replace the +/// standard builtin declaration with one that uses the same address space +/// as the call. +/// +/// \returns nullptr If this builtin is not a candidate for a rewrite i.e. +/// it does not contain any pointer arguments without +/// an address space qualifer. Otherwise the rewritten +/// FunctionDecl is returned. +/// TODO: Handle pointer return types. +static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, + const FunctionDecl *FDecl, + MultiExprArg ArgExprs) { + + QualType DeclType = FDecl->getType(); + const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(DeclType); + + if (!Context.BuiltinInfo.hasPtrArgsOrResult(FDecl->getBuiltinID()) || + !FT || FT->isVariadic() || ArgExprs.size() != FT->getNumParams()) + return nullptr; + + bool NeedsNewDecl = false; + unsigned i = 0; + SmallVector<QualType, 8> OverloadParams; + + for (QualType ParamType : FT->param_types()) { + + // Convert array arguments to pointer to simplify type lookup. + Expr *Arg = Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]).get(); + QualType ArgType = Arg->getType(); + if (!ParamType->isPointerType() || + ParamType.getQualifiers().hasAddressSpace() || + !ArgType->isPointerType() || + !ArgType->getPointeeType().getQualifiers().hasAddressSpace()) { + OverloadParams.push_back(ParamType); + continue; + } + + NeedsNewDecl = true; + unsigned AS = ArgType->getPointeeType().getQualifiers().getAddressSpace(); + + QualType PointeeType = ParamType->getPointeeType(); + PointeeType = Context.getAddrSpaceQualType(PointeeType, AS); + OverloadParams.push_back(Context.getPointerType(PointeeType)); + } + + if (!NeedsNewDecl) + return nullptr; + + FunctionProtoType::ExtProtoInfo EPI; + QualType OverloadTy = Context.getFunctionType(FT->getReturnType(), + OverloadParams, EPI); + DeclContext *Parent = Context.getTranslationUnitDecl(); + FunctionDecl *OverloadDecl = FunctionDecl::Create(Context, Parent, + FDecl->getLocation(), + FDecl->getLocation(), + FDecl->getIdentifier(), + OverloadTy, + /*TInfo=*/nullptr, + SC_Extern, false, + /*hasPrototype=*/true); + SmallVector<ParmVarDecl*, 16> Params; + FT = cast<FunctionProtoType>(OverloadTy); + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { + QualType ParamType = FT->getParamType(i); + ParmVarDecl *Parm = + ParmVarDecl::Create(Context, OverloadDecl, SourceLocation(), + SourceLocation(), nullptr, ParamType, + /*TInfo=*/nullptr, SC_None, nullptr); + Parm->setScopeInfo(0, i); + Params.push_back(Parm); + } + OverloadDecl->setParams(Params); + return OverloadDecl; +} + /// 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. @@ -4661,10 +4803,24 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn)) if (UnOp->getOpcode() == UO_AddrOf) NakedFn = UnOp->getSubExpr()->IgnoreParens(); - - if (isa<DeclRefExpr>(NakedFn)) + + if (isa<DeclRefExpr>(NakedFn)) { NDecl = cast<DeclRefExpr>(NakedFn)->getDecl(); - else if (isa<MemberExpr>(NakedFn)) + + FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl); + if (FDecl && FDecl->getBuiltinID()) { + // Rewrite the function decl for this builtin by replacing paramaters + // with no explicit address space with the address space of the arguments + // in ArgExprs. + if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) { + NDecl = FDecl; + Fn = DeclRefExpr::Create(Context, FDecl->getQualifierLoc(), + SourceLocation(), FDecl, false, + SourceLocation(), FDecl->getType(), + Fn->getValueKind(), FDecl); + } + } + } else if (isa<MemberExpr>(NakedFn)) NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl(); if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) { @@ -5516,47 +5672,24 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, } /// \brief Return false if the condition expression is valid, true otherwise. -static bool checkCondition(Sema &S, Expr *Cond) { +static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) { QualType CondTy = Cond->getType(); + // OpenCL v1.1 s6.3.i says the condition cannot be a floating point type. + if (S.getLangOpts().OpenCL && CondTy->isFloatingType()) { + S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_nonfloat) + << CondTy << Cond->getSourceRange(); + return true; + } + // C99 6.5.15p2 if (CondTy->isScalarType()) return false; - // OpenCL v1.1 s6.3.i says the condition is allowed to be a vector or scalar. - if (S.getLangOpts().OpenCL && CondTy->isVectorType()) - return false; - - // Emit the proper error message. - S.Diag(Cond->getLocStart(), S.getLangOpts().OpenCL ? - diag::err_typecheck_cond_expect_scalar : - diag::err_typecheck_cond_expect_scalar_or_vector) - << CondTy; + S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_scalar) + << CondTy << Cond->getSourceRange(); return true; } -/// \brief Return false if the two expressions can be converted to a vector, -/// true otherwise -static bool checkConditionalConvertScalarsToVectors(Sema &S, ExprResult &LHS, - ExprResult &RHS, - QualType CondTy) { - // Both operands should be of scalar type. - if (!LHS.get()->getType()->isScalarType()) { - S.Diag(LHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) - << CondTy; - return true; - } - if (!RHS.get()->getType()->isScalarType()) { - S.Diag(RHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) - << CondTy; - return true; - } - - // Implicity convert these scalars to the type of the condition. - LHS = S.ImpCastExprToType(LHS.get(), CondTy, CK_IntegralCast); - RHS = S.ImpCastExprToType(RHS.get(), CondTy, CK_IntegralCast); - return false; -} - /// \brief Handle when one or both operands are void type. static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS, ExprResult &RHS) { @@ -5773,6 +5906,184 @@ static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int, return true; } +/// \brief Simple conversion between integer and floating point types. +/// +/// Used when handling the OpenCL conditional operator where the +/// condition is a vector while the other operands are scalar. +/// +/// OpenCL v1.1 s6.3.i and s6.11.6 together require that the scalar +/// types are either integer or floating type. Between the two +/// operands, the type with the higher rank is defined as the "result +/// type". The other operand needs to be promoted to the same type. No +/// other type promotion is allowed. We cannot use +/// UsualArithmeticConversions() for this purpose, since it always +/// promotes promotable types. +static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS, + ExprResult &RHS, + SourceLocation QuestionLoc) { + LHS = S.DefaultFunctionArrayLvalueConversion(LHS.get()); + if (LHS.isInvalid()) + return QualType(); + RHS = S.DefaultFunctionArrayLvalueConversion(RHS.get()); + if (RHS.isInvalid()) + return QualType(); + + // For conversion purposes, we ignore any qualifiers. + // For example, "const float" and "float" are equivalent. + QualType LHSType = + S.Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType(); + QualType RHSType = + S.Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType(); + + if (!LHSType->isIntegerType() && !LHSType->isRealFloatingType()) { + S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_int_float) + << LHSType << LHS.get()->getSourceRange(); + return QualType(); + } + + if (!RHSType->isIntegerType() && !RHSType->isRealFloatingType()) { + S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_int_float) + << RHSType << RHS.get()->getSourceRange(); + return QualType(); + } + + // If both types are identical, no conversion is needed. + if (LHSType == RHSType) + return LHSType; + + // Now handle "real" floating types (i.e. float, double, long double). + if (LHSType->isRealFloatingType() || RHSType->isRealFloatingType()) + return handleFloatConversion(S, LHS, RHS, LHSType, RHSType, + /*IsCompAssign = */ false); + + // Finally, we have two differing integer types. + return handleIntegerConversion<doIntegralCast, doIntegralCast> + (S, LHS, RHS, LHSType, RHSType, /*IsCompAssign = */ false); +} + +/// \brief Convert scalar operands to a vector that matches the +/// condition in length. +/// +/// Used when handling the OpenCL conditional operator where the +/// condition is a vector while the other operands are scalar. +/// +/// We first compute the "result type" for the scalar operands +/// according to OpenCL v1.1 s6.3.i. Both operands are then converted +/// into a vector of that type where the length matches the condition +/// vector type. s6.11.6 requires that the element types of the result +/// and the condition must have the same number of bits. +static QualType +OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS, ExprResult &RHS, + QualType CondTy, SourceLocation QuestionLoc) { + QualType ResTy = OpenCLArithmeticConversions(S, LHS, RHS, QuestionLoc); + if (ResTy.isNull()) return QualType(); + + const VectorType *CV = CondTy->getAs<VectorType>(); + assert(CV); + + // Determine the vector result type + unsigned NumElements = CV->getNumElements(); + QualType VectorTy = S.Context.getExtVectorType(ResTy, NumElements); + + // Ensure that all types have the same number of bits + if (S.Context.getTypeSize(CV->getElementType()) + != S.Context.getTypeSize(ResTy)) { + // Since VectorTy is created internally, it does not pretty print + // with an OpenCL name. Instead, we just print a description. + std::string EleTyName = ResTy.getUnqualifiedType().getAsString(); + SmallString<64> Str; + llvm::raw_svector_ostream OS(Str); + OS << "(vector of " << NumElements << " '" << EleTyName << "' values)"; + S.Diag(QuestionLoc, diag::err_conditional_vector_element_size) + << CondTy << OS.str(); + return QualType(); + } + + // Convert operands to the vector result type + LHS = S.ImpCastExprToType(LHS.get(), VectorTy, CK_VectorSplat); + RHS = S.ImpCastExprToType(RHS.get(), VectorTy, CK_VectorSplat); + + return VectorTy; +} + +/// \brief Return false if this is a valid OpenCL condition vector +static bool checkOpenCLConditionVector(Sema &S, Expr *Cond, + SourceLocation QuestionLoc) { + // OpenCL v1.1 s6.11.6 says the elements of the vector must be of + // integral type. + const VectorType *CondTy = Cond->getType()->getAs<VectorType>(); + assert(CondTy); + QualType EleTy = CondTy->getElementType(); + if (EleTy->isIntegerType()) return false; + + S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_nonfloat) + << Cond->getType() << Cond->getSourceRange(); + return true; +} + +/// \brief Return false if the vector condition type and the vector +/// result type are compatible. +/// +/// OpenCL v1.1 s6.11.6 requires that both vector types have the same +/// number of elements, and their element types have the same number +/// of bits. +static bool checkVectorResult(Sema &S, QualType CondTy, QualType VecResTy, + SourceLocation QuestionLoc) { + const VectorType *CV = CondTy->getAs<VectorType>(); + const VectorType *RV = VecResTy->getAs<VectorType>(); + assert(CV && RV); + + if (CV->getNumElements() != RV->getNumElements()) { + S.Diag(QuestionLoc, diag::err_conditional_vector_size) + << CondTy << VecResTy; + return true; + } + + QualType CVE = CV->getElementType(); + QualType RVE = RV->getElementType(); + + if (S.Context.getTypeSize(CVE) != S.Context.getTypeSize(RVE)) { + S.Diag(QuestionLoc, diag::err_conditional_vector_element_size) + << CondTy << VecResTy; + return true; + } + + return false; +} + +/// \brief Return the resulting type for the conditional operator in +/// OpenCL (aka "ternary selection operator", OpenCL v1.1 +/// s6.3.i) when the condition is a vector type. +static QualType +OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond, + ExprResult &LHS, ExprResult &RHS, + SourceLocation QuestionLoc) { + Cond = S.DefaultFunctionArrayLvalueConversion(Cond.get()); + if (Cond.isInvalid()) + return QualType(); + QualType CondTy = Cond.get()->getType(); + + if (checkOpenCLConditionVector(S, Cond.get(), QuestionLoc)) + return QualType(); + + // If either operand is a vector then find the vector type of the + // result as specified in OpenCL v1.1 s6.3.i. + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) { + QualType VecResTy = S.CheckVectorOperands(LHS, RHS, QuestionLoc, + /*isCompAssign*/false); + if (VecResTy.isNull()) return QualType(); + // The result type must match the condition type as specified in + // OpenCL v1.1 s6.11.6. + if (checkVectorResult(S, CondTy, VecResTy, QuestionLoc)) + return QualType(); + return VecResTy; + } + + // Both operands are scalar. + return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc); +} + /// 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 @@ -5796,11 +6107,16 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, VK = VK_RValue; OK = OK_Ordinary; + // The OpenCL operator with a vector condition is sufficiently + // different to merit its own checker. + if (getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) + return OpenCLCheckVectorConditional(*this, Cond, LHS, RHS, QuestionLoc); + // First, check the condition. Cond = UsualUnaryConversions(Cond.get()); if (Cond.isInvalid()) return QualType(); - if (checkCondition(*this, Cond.get())) + if (checkCondition(*this, Cond.get(), QuestionLoc)) return QualType(); // Now check the two expressions. @@ -5812,17 +6128,9 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); - QualType CondTy = Cond.get()->getType(); QualType LHSTy = LHS.get()->getType(); QualType RHSTy = RHS.get()->getType(); - // If the condition is a vector, and both operands are scalar, - // attempt to implicity convert them to the vector type to act like the - // built in select. (OpenCL v1.1 s6.3.i) - if (getLangOpts().OpenCL && CondTy->isVectorType()) - if (checkConditionalConvertScalarsToVectors(*this, LHS, RHS, CondTy)) - return QualType(); - // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { @@ -6116,6 +6424,8 @@ static bool ExprLooksBoolean(Expr *E) { return IsLogicOp(OP->getOpcode()); if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E)) return OP->getOpcode() == UO_LNot; + if (E->getType()->isPointerType()) + return true; return false; } @@ -6218,6 +6528,8 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, DiagnoseConditionalPrecedence(*this, QuestionLoc, Cond.get(), LHS.get(), RHS.get()); + CheckBoolLikeConversion(Cond.get(), QuestionLoc); + if (!commonExpr) return new (Context) ConditionalOperator(Cond.get(), QuestionLoc, LHS.get(), ColonLoc, @@ -7178,9 +7490,12 @@ static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc, /// \returns True if pointer has incomplete type static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, Expr *Operand) { - assert(Operand->getType()->isAnyPointerType() && - !Operand->getType()->isDependentType()); - QualType PointeeTy = Operand->getType()->getPointeeType(); + QualType ResType = Operand->getType(); + if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>()) + ResType = ResAtomicType->getValueType(); + + assert(ResType->isAnyPointerType() && !ResType->isDependentType()); + QualType PointeeTy = ResType->getPointeeType(); return S.RequireCompleteType(Loc, PointeeTy, diag::err_typecheck_arithmetic_incomplete_type, PointeeTy, Operand->getSourceRange()); @@ -7196,9 +7511,13 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, /// \returns True when the operand is valid to use (even if as an extension). static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc, Expr *Operand) { - if (!Operand->getType()->isAnyPointerType()) return true; + QualType ResType = Operand->getType(); + if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>()) + ResType = ResAtomicType->getValueType(); - QualType PointeeTy = Operand->getType()->getPointeeType(); + if (!ResType->isAnyPointerType()) return true; + + QualType PointeeTy = ResType->getPointeeType(); if (PointeeTy->isVoidType()) { diagnoseArithmeticOnVoidPointer(S, Loc, Operand); return !S.getLangOpts().CPlusPlus; @@ -7558,7 +7877,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, llvm::APSInt Right; // Check right/shifter operand if (RHS.get()->isValueDependent() || - !RHS.get()->isIntegerConstantExpr(Right, S.Context)) + !RHS.get()->EvaluateAsInt(Right, S.Context)) return; if (Right.isNegative()) { @@ -7605,7 +7924,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, // turned off separately if needed. if (LeftBits == ResultBits - 1) { S.Diag(Loc, diag::warn_shift_result_sets_sign_bit) - << HexResult.str() << LHSType + << HexResult << LHSType << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return; } @@ -7616,6 +7935,69 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, << RHS.get()->getSourceRange(); } +/// \brief Return the resulting type when an OpenCL vector is shifted +/// by a scalar or vector shift amount. +static QualType checkOpenCLVectorShift(Sema &S, + ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, bool IsCompAssign) { + // OpenCL v1.1 s6.3.j says RHS can be a vector only if LHS is a vector. + if (!LHS.get()->getType()->isVectorType()) { + S.Diag(Loc, diag::err_shift_rhs_only_vector) + << RHS.get()->getType() << LHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + + if (!IsCompAssign) { + LHS = S.UsualUnaryConversions(LHS.get()); + if (LHS.isInvalid()) return QualType(); + } + + RHS = S.UsualUnaryConversions(RHS.get()); + if (RHS.isInvalid()) return QualType(); + + QualType LHSType = LHS.get()->getType(); + const VectorType *LHSVecTy = LHSType->getAs<VectorType>(); + QualType LHSEleType = LHSVecTy->getElementType(); + + // Note that RHS might not be a vector. + QualType RHSType = RHS.get()->getType(); + const VectorType *RHSVecTy = RHSType->getAs<VectorType>(); + QualType RHSEleType = RHSVecTy ? RHSVecTy->getElementType() : RHSType; + + // OpenCL v1.1 s6.3.j says that the operands need to be integers. + if (!LHSEleType->isIntegerType()) { + S.Diag(Loc, diag::err_typecheck_expect_int) + << LHS.get()->getType() << LHS.get()->getSourceRange(); + return QualType(); + } + + if (!RHSEleType->isIntegerType()) { + S.Diag(Loc, diag::err_typecheck_expect_int) + << RHS.get()->getType() << RHS.get()->getSourceRange(); + return QualType(); + } + + if (RHSVecTy) { + // OpenCL v1.1 s6.3.j says that for vector types, the operators + // are applied component-wise. So if RHS is a vector, then ensure + // that the number of elements is the same as LHS... + if (RHSVecTy->getNumElements() != LHSVecTy->getNumElements()) { + S.Diag(Loc, diag::err_typecheck_vector_lengths_not_equal) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + } else { + // ...else expand RHS to match the number of elements in LHS. + QualType VecTy = + S.Context.getExtVectorType(RHSEleType, LHSVecTy->getNumElements()); + RHS = S.ImpCastExprToType(RHS.get(), VecTy, CK_VectorSplat); + } + + return LHSType; +} + // C99 6.5.7 QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, @@ -7624,8 +8006,11 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS, // Vector shifts promote their scalar inputs to vector type. if (LHS.get()->getType()->isVectorType() || - RHS.get()->getType()->isVectorType()) + RHS.get()->getType()->isVectorType()) { + if (LangOpts.OpenCL) + return checkOpenCLVectorShift(*this, LHS, RHS, Loc, IsCompAssign); return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign); + } // Shifts don't perform usual arithmetic conversions, they just do integer // promotions on each operand. C99 6.5.7p3 @@ -7807,8 +8192,7 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { if (Type->isObjCIdType()) { // For 'id', just check the global pool. Method = S.LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(), - /*receiverId=*/true, - /*warn=*/false); + /*receiverId=*/true); } else { // Check protocols. Method = S.LookupMethodInQualifiedType(IsEqualSel, Type, @@ -8614,6 +8998,139 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) { return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda); } +static bool IsTypeModifiable(QualType Ty, bool IsDereference) { + Ty = Ty.getNonReferenceType(); + if (IsDereference && Ty->isPointerType()) + Ty = Ty->getPointeeType(); + return !Ty.isConstQualified(); +} + +/// Emit the "read-only variable not assignable" error and print notes to give +/// more information about why the variable is not assignable, such as pointing +/// to the declaration of a const variable, showing that a method is const, or +/// that the function is returning a const reference. +static void DiagnoseConstAssignment(Sema &S, const Expr *E, + SourceLocation Loc) { + // Update err_typecheck_assign_const and note_typecheck_assign_const + // when this enum is changed. + enum { + ConstFunction, + ConstVariable, + ConstMember, + ConstMethod, + ConstUnknown, // Keep as last element + }; + + SourceRange ExprRange = E->getSourceRange(); + + // Only emit one error on the first const found. All other consts will emit + // a note to the error. + bool DiagnosticEmitted = false; + + // Track if the current expression is the result of a derefence, and if the + // next checked expression is the result of a derefence. + bool IsDereference = false; + bool NextIsDereference = false; + + // Loop to process MemberExpr chains. + while (true) { + IsDereference = NextIsDereference; + NextIsDereference = false; + + E = E->IgnoreParenImpCasts(); + if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + NextIsDereference = ME->isArrow(); + const ValueDecl *VD = ME->getMemberDecl(); + if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) { + // Mutable fields can be modified even if the class is const. + if (Field->isMutable()) { + assert(DiagnosticEmitted && "Expected diagnostic not emitted."); + break; + } + + if (!IsTypeModifiable(Field->getType(), IsDereference)) { + if (!DiagnosticEmitted) { + S.Diag(Loc, diag::err_typecheck_assign_const) + << ExprRange << ConstMember << false /*static*/ << Field + << Field->getType(); + DiagnosticEmitted = true; + } + S.Diag(VD->getLocation(), diag::note_typecheck_assign_const) + << ConstMember << false /*static*/ << Field << Field->getType() + << Field->getSourceRange(); + } + E = ME->getBase(); + continue; + } else if (const VarDecl *VDecl = dyn_cast<VarDecl>(VD)) { + if (VDecl->getType().isConstQualified()) { + if (!DiagnosticEmitted) { + S.Diag(Loc, diag::err_typecheck_assign_const) + << ExprRange << ConstMember << true /*static*/ << VDecl + << VDecl->getType(); + DiagnosticEmitted = true; + } + S.Diag(VD->getLocation(), diag::note_typecheck_assign_const) + << ConstMember << true /*static*/ << VDecl << VDecl->getType() + << VDecl->getSourceRange(); + } + // Static fields do not inherit constness from parents. + break; + } + break; + } // End MemberExpr + break; + } + + if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { + // Function calls + const FunctionDecl *FD = CE->getDirectCallee(); + if (!IsTypeModifiable(FD->getReturnType(), IsDereference)) { + if (!DiagnosticEmitted) { + S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange + << ConstFunction << FD; + DiagnosticEmitted = true; + } + S.Diag(FD->getReturnTypeSourceRange().getBegin(), + diag::note_typecheck_assign_const) + << ConstFunction << FD << FD->getReturnType() + << FD->getReturnTypeSourceRange(); + } + } else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + // Point to variable declaration. + if (const ValueDecl *VD = DRE->getDecl()) { + if (!IsTypeModifiable(VD->getType(), IsDereference)) { + if (!DiagnosticEmitted) { + S.Diag(Loc, diag::err_typecheck_assign_const) + << ExprRange << ConstVariable << VD << VD->getType(); + DiagnosticEmitted = true; + } + S.Diag(VD->getLocation(), diag::note_typecheck_assign_const) + << ConstVariable << VD << VD->getType() << VD->getSourceRange(); + } + } + } else if (isa<CXXThisExpr>(E)) { + if (const DeclContext *DC = S.getFunctionLevelDeclContext()) { + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) { + if (MD->isConst()) { + if (!DiagnosticEmitted) { + S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange + << ConstMethod << MD; + DiagnosticEmitted = true; + } + S.Diag(MD->getLocation(), diag::note_typecheck_assign_const) + << ConstMethod << MD << MD->getSourceRange(); + } + } + } + } + + if (DiagnosticEmitted) + return; + + // Can't determine a more specific message, so display the generic error. + S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstUnknown; +} + /// 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) { @@ -8630,8 +9147,6 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { bool NeedType = false; switch (IsLV) { // C99 6.5.16p2 case Expr::MLV_ConstQualified: - DiagID = diag::err_typecheck_assign_const; - // Use a specialized diagnostic when we're assigning to an object // from an enclosing function or block. if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) { @@ -8670,14 +9185,24 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { if (Loc != OrigLoc) Assign = SourceRange(OrigLoc, OrigLoc); S.Diag(Loc, DiagID) << E->getSourceRange() << Assign; - // We need to preserve the AST regardless, so migration tool + // We need to preserve the AST regardless, so migration tool // can do its job. return false; } } } + // If none of the special cases above are triggered, then this is a + // simple const assignment. + if (DiagID == 0) { + DiagnoseConstAssignment(S, E, Loc); + return true; + } + break; + case Expr::MLV_ConstAddrSpace: + DiagnoseConstAssignment(S, E, Loc); + return true; case Expr::MLV_ArrayType: case Expr::MLV_ArrayTemporary: DiagID = diag::err_typecheck_array_not_modifiable_lvalue; @@ -9189,6 +9714,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { !getLangOpts().CPlusPlus) { AddressOfError = AO_Register_Variable; } + } else if (isa<MSPropertyDecl>(dcl)) { + AddressOfError = AO_Property_Expansion; } else if (isa<FunctionTemplateDecl>(dcl)) { return Context.OverloadTy; } else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) { @@ -11443,12 +11970,9 @@ void Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl, bool IsDecltype) { - ExprEvalContexts.push_back( - ExpressionEvaluationContextRecord(NewContext, - ExprCleanupObjects.size(), - ExprNeedsCleanups, - LambdaContextDecl, - IsDecltype)); + ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), + ExprNeedsCleanups, LambdaContextDecl, + IsDecltype); ExprNeedsCleanups = false; if (!MaybeODRUseExprs.empty()) std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); @@ -11580,7 +12104,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, // We (incorrectly) mark overload resolution as an unevaluated context, so we // can just check that here. Skip the rest of this function if we've already // marked the function as used. - if (Func->isUsed(false) || !IsPotentiallyEvaluatedContext(*this)) { + if (Func->isUsed(/*CheckUsedAttr=*/false) || + !IsPotentiallyEvaluatedContext(*this)) { // C++11 [temp.inst]p3: // Unless a function template specialization has been explicitly // instantiated or explicitly specialized, the function template @@ -11635,7 +12160,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, return; DefineImplicitDestructor(Loc, Destructor); } - if (Destructor->isVirtual()) + if (Destructor->isVirtual() && getLangOpts().AppleKext) MarkVTableUsed(Loc, Destructor->getParent()); } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) { if (MethodDecl->isOverloadedOperator() && @@ -11655,7 +12180,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion); else DefineImplicitLambdaToFunctionPointerConversion(Loc, Conversion); - } else if (MethodDecl->isVirtual()) + } else if (MethodDecl->isVirtual() && getLangOpts().AppleKext) MarkVTableUsed(Loc, MethodDecl->getParent()); } @@ -11727,7 +12252,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, if (mightHaveNonExternalLinkage(Func)) UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc)); else if (Func->getMostRecentDecl()->isInlined() && - (LangOpts.CPlusPlus || !LangOpts.GNUInline) && + !LangOpts.GNUInline && !Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>()) UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc)); } @@ -12029,13 +12554,11 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, } /// \brief Create a field within the lambda class for the variable -/// being captured. Handle Array captures. -static ExprResult addAsFieldToClosureType(Sema &S, - LambdaScopeInfo *LSI, - VarDecl *Var, QualType FieldType, - QualType DeclRefType, - SourceLocation Loc, - bool RefersToCapturedVariable) { +/// being captured. +static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, VarDecl *Var, + QualType FieldType, QualType DeclRefType, + SourceLocation Loc, + bool RefersToCapturedVariable) { CXXRecordDecl *Lambda = LSI->Lambda; // Build the non-static data member. @@ -12046,111 +12569,8 @@ static ExprResult addAsFieldToClosureType(Sema &S, Field->setImplicit(true); Field->setAccess(AS_private); Lambda->addDecl(Field); - - // C++11 [expr.prim.lambda]p21: - // When the lambda-expression is evaluated, the entities that - // are captured by copy are used to direct-initialize each - // corresponding non-static data member of the resulting closure - // object. (For array members, the array elements are - // direct-initialized in increasing subscript order.) These - // initializations are performed in the (unspecified) order in - // which the non-static data members are declared. - - // Introduce a new evaluation context for the initialization, so - // that temporaries introduced as part of the capture are retained - // to be re-"exported" from the lambda expression itself. - EnterExpressionEvaluationContext scope(S, Sema::PotentiallyEvaluated); - - // C++ [expr.prim.labda]p12: - // An entity captured by a lambda-expression is odr-used (3.2) in - // the scope containing the lambda-expression. - Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToCapturedVariable, - DeclRefType, VK_LValue, Loc); - Var->setReferenced(true); - Var->markUsed(S.Context); - - // When the field has array type, create index variables for each - // dimension of the array. We use these index variables to subscript - // the source array, and other clients (e.g., CodeGen) will perform - // the necessary iteration with these index variables. - SmallVector<VarDecl *, 4> IndexVariables; - QualType BaseType = FieldType; - QualType SizeType = S.Context.getSizeType(); - LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size()); - while (const ConstantArrayType *Array - = S.Context.getAsConstantArrayType(BaseType)) { - // Create the iteration variable for this array index. - IdentifierInfo *IterationVarName = nullptr; - { - SmallString<8> Str; - llvm::raw_svector_ostream OS(Str); - OS << "__i" << IndexVariables.size(); - IterationVarName = &S.Context.Idents.get(OS.str()); - } - VarDecl *IterationVar - = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, - IterationVarName, SizeType, - S.Context.getTrivialTypeSourceInfo(SizeType, Loc), - SC_None); - IndexVariables.push_back(IterationVar); - LSI->ArrayIndexVars.push_back(IterationVar); - - // Create a reference to the iteration variable. - ExprResult IterationVarRef - = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); - assert(!IterationVarRef.isInvalid() && - "Reference to invented variable cannot fail!"); - IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get()); - assert(!IterationVarRef.isInvalid() && - "Conversion of invented variable cannot fail!"); - - // Subscript the array with this iteration variable. - ExprResult Subscript = S.CreateBuiltinArraySubscriptExpr( - Ref, Loc, IterationVarRef.get(), Loc); - if (Subscript.isInvalid()) { - S.CleanupVarDeclMarking(); - S.DiscardCleanupsInEvaluationContext(); - return ExprError(); - } - - Ref = Subscript.get(); - BaseType = Array->getElementType(); - } - - // Construct the entity that we will be initializing. For an array, this - // will be first element in the array, which may require several levels - // of array-subscript entities. - SmallVector<InitializedEntity, 4> Entities; - Entities.reserve(1 + IndexVariables.size()); - Entities.push_back( - InitializedEntity::InitializeLambdaCapture(Var->getIdentifier(), - Field->getType(), Loc)); - for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) - Entities.push_back(InitializedEntity::InitializeElement(S.Context, - 0, - Entities.back())); - - InitializationKind InitKind - = InitializationKind::CreateDirect(Loc, Loc, Loc); - InitializationSequence Init(S, Entities.back(), InitKind, Ref); - ExprResult Result(true); - if (!Init.Diagnose(S, Entities.back(), InitKind, Ref)) - Result = Init.Perform(S, Entities.back(), InitKind, Ref); - - // If this initialization requires any cleanups (e.g., due to a - // default argument to a copy constructor), note that for the - // lambda. - if (S.ExprNeedsCleanups) - LSI->ExprNeedsCleanups = true; - - // Exit the expression evaluation context used for the capture. - S.CleanupVarDeclMarking(); - S.DiscardCleanupsInEvaluationContext(); - return Result; } - - /// \brief Capture the given variable in the lambda. static bool captureInLambda(LambdaScopeInfo *LSI, VarDecl *Var, @@ -12228,14 +12648,9 @@ static bool captureInLambda(LambdaScopeInfo *LSI, } // Capture this variable in the lambda. - Expr *CopyExpr = nullptr; - if (BuildAndDiagnose) { - ExprResult Result = addAsFieldToClosureType(S, LSI, Var, - CaptureType, DeclRefType, Loc, - RefersToCapturedVariable); - if (!Result.isInvalid()) - CopyExpr = Result.get(); - } + if (BuildAndDiagnose) + addAsFieldToClosureType(S, LSI, Var, CaptureType, DeclRefType, Loc, + RefersToCapturedVariable); // Compute the type of a reference to this captured variable. if (ByRef) @@ -12254,18 +12669,20 @@ static bool captureInLambda(LambdaScopeInfo *LSI, // Add the capture. if (BuildAndDiagnose) LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable, - Loc, EllipsisLoc, CaptureType, CopyExpr); + Loc, EllipsisLoc, CaptureType, /*CopyExpr=*/nullptr); return true; } -bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, - TryCaptureKind Kind, SourceLocation EllipsisLoc, - bool BuildAndDiagnose, - QualType &CaptureType, - QualType &DeclRefType, - const unsigned *const FunctionScopeIndexToStopAt) { - bool Nested = Var->isInitCapture(); +bool Sema::tryCaptureVariable( + VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind, + SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, + QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt) { + // An init-capture is notionally from the context surrounding its + // declaration, but its parent DC is the lambda class. + DeclContext *VarDC = Var->getDeclContext(); + if (Var->isInitCapture()) + VarDC = VarDC->getParent(); DeclContext *DC = CurContext; const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt @@ -12281,9 +12698,9 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, } - // If the variable is declared in the current context (and is not an - // init-capture), there is no need to capture it. - if (!Nested && Var->getDeclContext() == DC) return true; + // If the variable is declared in the current context, there is no need to + // capture it. + if (VarDC == DC) return true; // Capture global variables if it is required to use private copy of this // variable. @@ -12301,6 +12718,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, // the variable. CaptureType = Var->getType(); DeclRefType = CaptureType.getNonReferenceType(); + bool Nested = false; bool Explicit = (Kind != TryCapture_Implicit); unsigned FunctionScopesIndex = MaxFunctionScopesIndex; do { @@ -12501,7 +12919,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, FunctionScopesIndex--; DC = ParentDC; Explicit = false; - } while (!Var->getDeclContext()->Equals(DC)); + } while (!VarDC->Equals(DC)); // Walk back down the scope stack, (e.g. from outer lambda to inner lambda) // computing the type of the capture at each step, checking type-specific @@ -13740,7 +14158,17 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { // Bound member functions. case BuiltinType::BoundMember: { ExprResult result = E; - tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function), + const Expr *BME = E->IgnoreParens(); + PartialDiagnostic PD = PDiag(diag::err_bound_member_function); + // Try to give a nicer diagnostic if it is a bound member that we recognize. + if (isa<CXXPseudoDestructorExpr>(BME)) { + PD = PDiag(diag::err_dtor_expr_without_call) << /*pseudo-destructor*/ 1; + } else if (const auto *ME = dyn_cast<MemberExpr>(BME)) { + if (ME->getMemberNameInfo().getName().getNameKind() == + DeclarationName::CXXDestructorName) + PD = PDiag(diag::err_dtor_expr_without_call) << /*destructor*/ 0; + } + tryToRecoverWithCall(result, PD, /*complain*/ true); return result; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index a92b7ac..7e305ff 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -113,6 +113,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, bool isDependent = false; bool LookInScope = false; + if (SS.isInvalid()) + return ParsedType(); + // If we have an object type, it's because we are in a // pseudo-destructor-expression or a member access expression, and // we know what type we're looking for. @@ -644,37 +647,98 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw"; if (Ex && !Ex->isTypeDependent()) { - ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex, IsThrownVarInScope); - if (ExRes.isInvalid()) + QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType()); + if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex)) return ExprError(); - Ex = ExRes.get(); + + // Initialize the exception result. This implicitly weeds out + // abstract types or types with inaccessible copy constructors. + + // C++0x [class.copymove]p31: + // When certain criteria are met, an implementation is allowed to omit the + // copy/move construction of a class object [...] + // + // - in a throw-expression, when the operand is the name of a + // non-volatile automatic object (other than a function or + // catch-clause + // parameter) whose scope does not extend beyond the end of the + // innermost enclosing try-block (if there is one), the copy/move + // operation from the operand to the exception object (15.1) can be + // omitted by constructing the automatic object directly into the + // exception object + const VarDecl *NRVOVariable = nullptr; + if (IsThrownVarInScope) + NRVOVariable = getCopyElisionCandidate(QualType(), Ex, false); + + InitializedEntity Entity = InitializedEntity::InitializeException( + OpLoc, ExceptionObjectTy, + /*NRVO=*/NRVOVariable != nullptr); + ExprResult Res = PerformMoveOrCopyInitialization( + Entity, NRVOVariable, QualType(), Ex, IsThrownVarInScope); + if (Res.isInvalid()) + return ExprError(); + Ex = Res.get(); } - + return new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope); } -/// CheckCXXThrowOperand - Validate the operand of a throw. -ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, - bool IsThrownVarInScope) { - // C++ [except.throw]p3: - // A throw-expression initializes a temporary object, called the exception - // object, the type of which is determined by removing any top-level - // cv-qualifiers from the static type of the operand of throw and adjusting - // the type from "array of T" or "function returning T" to "pointer to T" - // or "pointer to function returning T", [...] - if (E->getType().hasQualifiers()) - E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp, - E->getValueKind()).get(); - - ExprResult Res = DefaultFunctionArrayConversion(E); - if (Res.isInvalid()) - return ExprError(); - E = Res.get(); +static void +collectPublicBases(CXXRecordDecl *RD, + llvm::DenseMap<CXXRecordDecl *, unsigned> &SubobjectsSeen, + llvm::SmallPtrSetImpl<CXXRecordDecl *> &VBases, + llvm::SetVector<CXXRecordDecl *> &PublicSubobjectsSeen, + bool ParentIsPublic) { + for (const CXXBaseSpecifier &BS : RD->bases()) { + CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl(); + bool NewSubobject; + // Virtual bases constitute the same subobject. Non-virtual bases are + // always distinct subobjects. + if (BS.isVirtual()) + NewSubobject = VBases.insert(BaseDecl).second; + else + NewSubobject = true; + + if (NewSubobject) + ++SubobjectsSeen[BaseDecl]; + + // Only add subobjects which have public access throughout the entire chain. + bool PublicPath = ParentIsPublic && BS.getAccessSpecifier() == AS_public; + if (PublicPath) + PublicSubobjectsSeen.insert(BaseDecl); + + // Recurse on to each base subobject. + collectPublicBases(BaseDecl, SubobjectsSeen, VBases, PublicSubobjectsSeen, + PublicPath); + } +} + +static void getUnambiguousPublicSubobjects( + CXXRecordDecl *RD, llvm::SmallVectorImpl<CXXRecordDecl *> &Objects) { + llvm::DenseMap<CXXRecordDecl *, unsigned> SubobjectsSeen; + llvm::SmallSet<CXXRecordDecl *, 2> VBases; + llvm::SetVector<CXXRecordDecl *> PublicSubobjectsSeen; + SubobjectsSeen[RD] = 1; + PublicSubobjectsSeen.insert(RD); + collectPublicBases(RD, SubobjectsSeen, VBases, PublicSubobjectsSeen, + /*ParentIsPublic=*/true); + + for (CXXRecordDecl *PublicSubobject : PublicSubobjectsSeen) { + // Skip ambiguous objects. + if (SubobjectsSeen[PublicSubobject] > 1) + continue; + Objects.push_back(PublicSubobject); + } +} + +/// CheckCXXThrowOperand - Validate the operand of a throw. +bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, + QualType ExceptionObjectTy, Expr *E) { // If the type of the exception would be an incomplete type or a pointer // to an incomplete type other than (cv) void the program is ill-formed. - QualType Ty = E->getType(); + QualType Ty = ExceptionObjectTy; bool isPointer = false; if (const PointerType* Ptr = Ty->getAs<PointerType>()) { Ty = Ptr->getPointeeType(); @@ -682,49 +746,20 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, } if (!isPointer || !Ty->isVoidType()) { if (RequireCompleteType(ThrowLoc, Ty, - isPointer? diag::err_throw_incomplete_ptr - : diag::err_throw_incomplete, + isPointer ? diag::err_throw_incomplete_ptr + : diag::err_throw_incomplete, E->getSourceRange())) - return ExprError(); + return true; - if (RequireNonAbstractType(ThrowLoc, E->getType(), + if (RequireNonAbstractType(ThrowLoc, ExceptionObjectTy, diag::err_throw_abstract_type, E)) - return ExprError(); + return true; } - // Initialize the exception result. This implicitly weeds out - // abstract types or types with inaccessible copy constructors. - - // C++0x [class.copymove]p31: - // When certain criteria are met, an implementation is allowed to omit the - // copy/move construction of a class object [...] - // - // - in a throw-expression, when the operand is the name of a - // non-volatile automatic object (other than a function or catch-clause - // parameter) whose scope does not extend beyond the end of the - // innermost enclosing try-block (if there is one), the copy/move - // operation from the operand to the exception object (15.1) can be - // omitted by constructing the automatic object directly into the - // exception object - const VarDecl *NRVOVariable = nullptr; - if (IsThrownVarInScope) - NRVOVariable = getCopyElisionCandidate(QualType(), E, false); - - InitializedEntity Entity = - InitializedEntity::InitializeException(ThrowLoc, E->getType(), - /*NRVO=*/NRVOVariable != nullptr); - Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable, - QualType(), E, - IsThrownVarInScope); - if (Res.isInvalid()) - return ExprError(); - E = Res.get(); - // If the exception has class type, we need additional handling. - const RecordType *RecordTy = Ty->getAs<RecordType>(); - if (!RecordTy) - return E; - CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); + CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + if (!RD) + return false; // If we are throwing a polymorphic class type or pointer thereof, // exception handling will make use of the vtable. @@ -732,22 +767,69 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, // If a pointer is thrown, the referenced object will not be destroyed. if (isPointer) - return E; + return false; // If the class has a destructor, we must be able to call it. - if (RD->hasIrrelevantDestructor()) - return E; + if (!RD->hasIrrelevantDestructor()) { + if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { + MarkFunctionReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_exception) << Ty); + if (DiagnoseUseOfDecl(Destructor, E->getExprLoc())) + return true; + } + } - CXXDestructorDecl *Destructor = LookupDestructor(RD); - if (!Destructor) - return E; + // The MSVC ABI creates a list of all types which can catch the exception + // object. This list also references the appropriate copy constructor to call + // if the object is caught by value and has a non-trivial copy constructor. + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + // We are only interested in the public, unambiguous bases contained within + // the exception object. Bases which are ambiguous or otherwise + // inaccessible are not catchable types. + llvm::SmallVector<CXXRecordDecl *, 2> UnambiguousPublicSubobjects; + getUnambiguousPublicSubobjects(RD, UnambiguousPublicSubobjects); + + for (CXXRecordDecl *Subobject : UnambiguousPublicSubobjects) { + // Attempt to lookup the copy constructor. Various pieces of machinery + // will spring into action, like template instantiation, which means this + // cannot be a simple walk of the class's decls. Instead, we must perform + // lookup and overload resolution. + CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0); + if (!CD) + continue; - MarkFunctionReferenced(E->getExprLoc(), Destructor); - CheckDestructorAccess(E->getExprLoc(), Destructor, - PDiag(diag::err_access_dtor_exception) << Ty); - if (DiagnoseUseOfDecl(Destructor, E->getExprLoc())) - return ExprError(); - return E; + // Mark the constructor referenced as it is used by this throw expression. + MarkFunctionReferenced(E->getExprLoc(), CD); + + // Skip this copy constructor if it is trivial, we don't need to record it + // in the catchable type data. + if (CD->isTrivial()) + continue; + + // The copy constructor is non-trivial, create a mapping from this class + // type to this constructor. + // N.B. The selection of copy constructor is not sensitive to this + // particular throw-site. Lookup will be performed at the catch-site to + // ensure that the copy constructor is, in fact, accessible (via + // friendship or any other means). + Context.addCopyConstructorForExceptionObject(Subobject, CD); + + // We don't keep the instantiated default argument expressions around so + // we must rebuild them here. + for (unsigned I = 1, E = CD->getNumParams(); I != E; ++I) { + // Skip any default arguments that we've already instantiated. + if (Context.getDefaultArgExprForConstructor(CD, I)) + continue; + + Expr *DefaultArg = + BuildCXXDefaultArgExpr(ThrowLoc, CD, CD->getParamDecl(I)).get(); + Context.addDefaultArgExprForConstructor(CD, I, DefaultArg); + } + } + } + + return false; } QualType Sema::getCurrentThisType() { @@ -982,18 +1064,21 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, Expr *Inner = Result.get(); if (CXXBindTemporaryExpr *BTE = dyn_cast_or_null<CXXBindTemporaryExpr>(Inner)) Inner = BTE->getSubExpr(); - if (isa<InitListExpr>(Inner)) { - // If the list-initialization doesn't involve a constructor call, we'll get - // the initializer-list (with corrected type) back, but that's not what we - // want, since it will be treated as an initializer list in further - // processing. Explicitly insert a cast here. + if (!isa<CXXTemporaryObjectExpr>(Inner)) { + // If we created a CXXTemporaryObjectExpr, that node also represents the + // functional cast. Otherwise, create an explicit cast to represent + // the syntactic form of a functional-style cast that was used here. + // + // FIXME: Creating a CXXFunctionalCastExpr around a CXXConstructExpr + // would give a more consistent AST representation than using a + // CXXTemporaryObjectExpr. It's also weird that the functional cast + // is sometimes handled by initialization and sometimes not. QualType ResultType = Result.get()->getType(); Result = CXXFunctionalCastExpr::Create( Context, ResultType, Expr::getValueKindForType(TInfo->getType()), TInfo, CK_NoOp, Result.get(), /*Path=*/nullptr, LParenLoc, RParenLoc); } - // FIXME: Improve AST representation? return Result; } @@ -1333,8 +1418,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, << ConvTy->isEnumeralType() << ConvTy; } - virtual SemaDiagnosticBuilder diagnoseConversion( - Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override { + SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) override { return S.Diag(Loc, S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_array_size_conversion @@ -2048,7 +2134,7 @@ void Sema::DeclareGlobalNewDelete() { void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, QualType Param1, QualType Param2, - bool AddMallocAttr) { + bool AddRestrictAttr) { DeclContext *GlobalCtx = Context.getTranslationUnitDecl(); unsigned NumParams = Param2.isNull() ? 1 : 2; @@ -2071,8 +2157,9 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // FIXME: Do we need to check for default arguments here? if (InitialParam1Type == Param1 && (NumParams == 1 || InitialParam2Type == Param2)) { - if (AddMallocAttr && !Func->hasAttr<MallocAttr>()) - Func->addAttr(MallocAttr::CreateImplicit(Context)); + if (AddRestrictAttr && !Func->hasAttr<RestrictAttr>()) + Func->addAttr(RestrictAttr::CreateImplicit( + Context, RestrictAttr::GNU_malloc)); // Make the function visible to name lookup, even if we found it in // an unimported module. It either is an implicitly-declared global // allocation function, or is suppressing that function. @@ -2110,9 +2197,14 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, SourceLocation(), Name, FnType, /*TInfo=*/nullptr, SC_None, false, true); Alloc->setImplicit(); + + // Implicit sized deallocation functions always have default visibility. + Alloc->addAttr(VisibilityAttr::CreateImplicit(Context, + VisibilityAttr::Default)); - if (AddMallocAttr) - Alloc->addAttr(MallocAttr::CreateImplicit(Context)); + if (AddRestrictAttr) + Alloc->addAttr( + RestrictAttr::CreateImplicit(Context, RestrictAttr::GNU_malloc)); ParmVarDecl *ParamDecls[2]; for (unsigned I = 0; I != NumParams; ++I) { @@ -2247,6 +2339,260 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, return false; } +namespace { +/// \brief Checks whether delete-expression, and new-expression used for +/// initializing deletee have the same array form. +class MismatchingNewDeleteDetector { +public: + enum MismatchResult { + /// Indicates that there is no mismatch or a mismatch cannot be proven. + NoMismatch, + /// Indicates that variable is initialized with mismatching form of \a new. + VarInitMismatches, + /// Indicates that member is initialized with mismatching form of \a new. + MemberInitMismatches, + /// Indicates that 1 or more constructors' definitions could not been + /// analyzed, and they will be checked again at the end of translation unit. + AnalyzeLater + }; + + /// \param EndOfTU True, if this is the final analysis at the end of + /// translation unit. False, if this is the initial analysis at the point + /// delete-expression was encountered. + explicit MismatchingNewDeleteDetector(bool EndOfTU) + : IsArrayForm(false), Field(nullptr), EndOfTU(EndOfTU), + HasUndefinedConstructors(false) {} + + /// \brief Checks whether pointee of a delete-expression is initialized with + /// matching form of new-expression. + /// + /// If return value is \c VarInitMismatches or \c MemberInitMismatches at the + /// point where delete-expression is encountered, then a warning will be + /// issued immediately. If return value is \c AnalyzeLater at the point where + /// delete-expression is seen, then member will be analyzed at the end of + /// translation unit. \c AnalyzeLater is returned iff at least one constructor + /// couldn't be analyzed. If at least one constructor initializes the member + /// with matching type of new, the return value is \c NoMismatch. + MismatchResult analyzeDeleteExpr(const CXXDeleteExpr *DE); + /// \brief Analyzes a class member. + /// \param Field Class member to analyze. + /// \param DeleteWasArrayForm Array form-ness of the delete-expression used + /// for deleting the \p Field. + MismatchResult analyzeField(FieldDecl *Field, bool DeleteWasArrayForm); + /// List of mismatching new-expressions used for initialization of the pointee + llvm::SmallVector<const CXXNewExpr *, 4> NewExprs; + /// Indicates whether delete-expression was in array form. + bool IsArrayForm; + FieldDecl *Field; + +private: + const bool EndOfTU; + /// \brief Indicates that there is at least one constructor without body. + bool HasUndefinedConstructors; + /// \brief Returns \c CXXNewExpr from given initialization expression. + /// \param E Expression used for initializing pointee in delete-expression. + /// E can be a single-element \c InitListExpr consisting of new-expression. + const CXXNewExpr *getNewExprFromInitListOrExpr(const Expr *E); + /// \brief Returns whether member is initialized with mismatching form of + /// \c new either by the member initializer or in-class initialization. + /// + /// If bodies of all constructors are not visible at the end of translation + /// unit or at least one constructor initializes member with the matching + /// form of \c new, mismatch cannot be proven, and this function will return + /// \c NoMismatch. + MismatchResult analyzeMemberExpr(const MemberExpr *ME); + /// \brief Returns whether variable is initialized with mismatching form of + /// \c new. + /// + /// If variable is initialized with matching form of \c new or variable is not + /// initialized with a \c new expression, this function will return true. + /// If variable is initialized with mismatching form of \c new, returns false. + /// \param D Variable to analyze. + bool hasMatchingVarInit(const DeclRefExpr *D); + /// \brief Checks whether the constructor initializes pointee with mismatching + /// form of \c new. + /// + /// Returns true, if member is initialized with matching form of \c new in + /// member initializer list. Returns false, if member is initialized with the + /// matching form of \c new in this constructor's initializer or given + /// constructor isn't defined at the point where delete-expression is seen, or + /// member isn't initialized by the constructor. + bool hasMatchingNewInCtor(const CXXConstructorDecl *CD); + /// \brief Checks whether member is initialized with matching form of + /// \c new in member initializer list. + bool hasMatchingNewInCtorInit(const CXXCtorInitializer *CI); + /// Checks whether member is initialized with mismatching form of \c new by + /// in-class initializer. + MismatchResult analyzeInClassInitializer(); +}; +} + +MismatchingNewDeleteDetector::MismatchResult +MismatchingNewDeleteDetector::analyzeDeleteExpr(const CXXDeleteExpr *DE) { + NewExprs.clear(); + assert(DE && "Expected delete-expression"); + IsArrayForm = DE->isArrayForm(); + const Expr *E = DE->getArgument()->IgnoreParenImpCasts(); + if (const MemberExpr *ME = dyn_cast<const MemberExpr>(E)) { + return analyzeMemberExpr(ME); + } else if (const DeclRefExpr *D = dyn_cast<const DeclRefExpr>(E)) { + if (!hasMatchingVarInit(D)) + return VarInitMismatches; + } + return NoMismatch; +} + +const CXXNewExpr * +MismatchingNewDeleteDetector::getNewExprFromInitListOrExpr(const Expr *E) { + assert(E != nullptr && "Expected a valid initializer expression"); + E = E->IgnoreParenImpCasts(); + if (const InitListExpr *ILE = dyn_cast<const InitListExpr>(E)) { + if (ILE->getNumInits() == 1) + E = dyn_cast<const CXXNewExpr>(ILE->getInit(0)->IgnoreParenImpCasts()); + } + + return dyn_cast_or_null<const CXXNewExpr>(E); +} + +bool MismatchingNewDeleteDetector::hasMatchingNewInCtorInit( + const CXXCtorInitializer *CI) { + const CXXNewExpr *NE = nullptr; + if (Field == CI->getMember() && + (NE = getNewExprFromInitListOrExpr(CI->getInit()))) { + if (NE->isArray() == IsArrayForm) + return true; + else + NewExprs.push_back(NE); + } + return false; +} + +bool MismatchingNewDeleteDetector::hasMatchingNewInCtor( + const CXXConstructorDecl *CD) { + if (CD->isImplicit()) + return false; + const FunctionDecl *Definition = CD; + if (!CD->isThisDeclarationADefinition() && !CD->isDefined(Definition)) { + HasUndefinedConstructors = true; + return EndOfTU; + } + for (const auto *CI : cast<const CXXConstructorDecl>(Definition)->inits()) { + if (hasMatchingNewInCtorInit(CI)) + return true; + } + return false; +} + +MismatchingNewDeleteDetector::MismatchResult +MismatchingNewDeleteDetector::analyzeInClassInitializer() { + assert(Field != nullptr && "This should be called only for members"); + if (const CXXNewExpr *NE = + getNewExprFromInitListOrExpr(Field->getInClassInitializer())) { + if (NE->isArray() != IsArrayForm) { + NewExprs.push_back(NE); + return MemberInitMismatches; + } + } + return NoMismatch; +} + +MismatchingNewDeleteDetector::MismatchResult +MismatchingNewDeleteDetector::analyzeField(FieldDecl *Field, + bool DeleteWasArrayForm) { + assert(Field != nullptr && "Analysis requires a valid class member."); + this->Field = Field; + IsArrayForm = DeleteWasArrayForm; + const CXXRecordDecl *RD = cast<const CXXRecordDecl>(Field->getParent()); + for (const auto *CD : RD->ctors()) { + if (hasMatchingNewInCtor(CD)) + return NoMismatch; + } + if (HasUndefinedConstructors) + return EndOfTU ? NoMismatch : AnalyzeLater; + if (!NewExprs.empty()) + return MemberInitMismatches; + return Field->hasInClassInitializer() ? analyzeInClassInitializer() + : NoMismatch; +} + +MismatchingNewDeleteDetector::MismatchResult +MismatchingNewDeleteDetector::analyzeMemberExpr(const MemberExpr *ME) { + assert(ME != nullptr && "Expected a member expression"); + if (FieldDecl *F = dyn_cast<FieldDecl>(ME->getMemberDecl())) + return analyzeField(F, IsArrayForm); + return NoMismatch; +} + +bool MismatchingNewDeleteDetector::hasMatchingVarInit(const DeclRefExpr *D) { + const CXXNewExpr *NE = nullptr; + if (const VarDecl *VD = dyn_cast<const VarDecl>(D->getDecl())) { + if (VD->hasInit() && (NE = getNewExprFromInitListOrExpr(VD->getInit())) && + NE->isArray() != IsArrayForm) { + NewExprs.push_back(NE); + } + } + return NewExprs.empty(); +} + +static void +DiagnoseMismatchedNewDelete(Sema &SemaRef, SourceLocation DeleteLoc, + const MismatchingNewDeleteDetector &Detector) { + SourceLocation EndOfDelete = SemaRef.getLocForEndOfToken(DeleteLoc); + FixItHint H; + if (!Detector.IsArrayForm) + H = FixItHint::CreateInsertion(EndOfDelete, "[]"); + else { + SourceLocation RSquare = Lexer::findLocationAfterToken( + DeleteLoc, tok::l_square, SemaRef.getSourceManager(), + SemaRef.getLangOpts(), true); + if (RSquare.isValid()) + H = FixItHint::CreateRemoval(SourceRange(EndOfDelete, RSquare)); + } + SemaRef.Diag(DeleteLoc, diag::warn_mismatched_delete_new) + << Detector.IsArrayForm << H; + + for (const auto *NE : Detector.NewExprs) + SemaRef.Diag(NE->getExprLoc(), diag::note_allocated_here) + << Detector.IsArrayForm; +} + +void Sema::AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE) { + if (Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) + return; + MismatchingNewDeleteDetector Detector(/*EndOfTU=*/false); + switch (Detector.analyzeDeleteExpr(DE)) { + case MismatchingNewDeleteDetector::VarInitMismatches: + case MismatchingNewDeleteDetector::MemberInitMismatches: { + DiagnoseMismatchedNewDelete(*this, DE->getLocStart(), Detector); + break; + } + case MismatchingNewDeleteDetector::AnalyzeLater: { + DeleteExprs[Detector.Field].push_back( + std::make_pair(DE->getLocStart(), DE->isArrayForm())); + break; + } + case MismatchingNewDeleteDetector::NoMismatch: + break; + } +} + +void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc, + bool DeleteWasArrayForm) { + MismatchingNewDeleteDetector Detector(/*EndOfTU=*/true); + switch (Detector.analyzeField(Field, DeleteWasArrayForm)) { + case MismatchingNewDeleteDetector::VarInitMismatches: + llvm_unreachable("This analysis should have been done for class members."); + case MismatchingNewDeleteDetector::AnalyzeLater: + llvm_unreachable("Analysis cannot be postponed any point beyond end of " + "translation unit."); + case MismatchingNewDeleteDetector::MemberInitMismatches: + DiagnoseMismatchedNewDelete(*this, DeleteLoc, Detector); + break; + case MismatchingNewDeleteDetector::NoMismatch: + break; + } +} + /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: /// @code ::delete ptr; @endcode /// or @@ -2362,12 +2708,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } } - // C++ [expr.delete]p2: - // [Note: a pointer to a const type can be the operand of a - // delete-expression; it is not necessary to cast away the constness - // (5.2.11) of the pointer expression before it is used as the operand - // of the delete-expression. ] - if (Pointee->isArrayType() && !ArrayForm) { Diag(StartLoc, diag::warn_delete_array_type) << Type << Ex.get()->getSourceRange() @@ -2442,7 +2782,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, DeleteName); MarkFunctionReferenced(StartLoc, OperatorDelete); - + // Check access and ambiguity of operator delete and destructor. if (PointeeRD) { if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { @@ -2452,9 +2792,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } } - return new (Context) CXXDeleteExpr( + CXXDeleteExpr *Result = new (Context) CXXDeleteExpr( Context.VoidTy, UseGlobal, ArrayForm, ArrayFormAsWritten, UsualArrayDeleteWantsSize, OperatorDelete, Ex.get(), StartLoc); + AnalyzeDeleteExprMismatch(Result); + return Result; } /// \brief Check the use of the given variable as a C++ condition in an if, @@ -2570,6 +2912,8 @@ static ExprResult BuildCXXCastArgument(Sema &S, S.CheckConstructorAccess(CastLoc, Constructor, InitializedEntity::InitializeTemporary(Ty), Constructor->getAccess()); + if (S.DiagnoseUseOfDecl(Method, CastLoc)) + return ExprError(); ExprResult Result = S.BuildCXXConstructExpr( CastLoc, Ty, cast<CXXConstructorDecl>(Method), @@ -2585,6 +2929,10 @@ static ExprResult BuildCXXCastArgument(Sema &S, case CK_UserDefinedConversion: { assert(!From->getType()->isPointerType() && "Arg can't have pointer type!"); + S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ nullptr, FoundDecl); + if (S.DiagnoseUseOfDecl(Method, CastLoc)) + return ExprError(); + // Create an implicit call expr that calls it. CXXConversionDecl *Conv = cast<CXXConversionDecl>(Method); ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Conv, @@ -2596,8 +2944,6 @@ static ExprResult BuildCXXCastArgument(Sema &S, CK_UserDefinedConversion, Result.get(), nullptr, Result.get()->getValueKind()); - S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ nullptr, FoundDecl); - return S.MaybeBindToTemporary(Result.get()); } } @@ -2628,7 +2974,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, FunctionDecl *FD = ICS.UserDefined.ConversionFunction; CastKind CastKind; QualType BeforeToType; - assert(FD && "FIXME: aggregate initialization from init list"); + assert(FD && "no conversion function for user-defined conversion seq"); if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) { CastKind = CK_UserDefinedConversion; @@ -2989,8 +3335,18 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; case ICK_Vector_Splat: - From = ImpCastExprToType(From, ToType, CK_VectorSplat, - VK_RValue, /*BasePath=*/nullptr, CCK).get(); + // Vector splat from any arithmetic type to a vector. + // Cast to the element type. + { + QualType elType = ToType->getAs<ExtVectorType>()->getElementType(); + if (elType != From->getType()) { + ExprResult E = From; + From = ImpCastExprToType(From, elType, + PrepareScalarCast(E, elType)).get(); + } + From = ImpCastExprToType(From, ToType, CK_VectorSplat, + VK_RValue, /*BasePath=*/nullptr, CCK).get(); + } break; case ICK_Complex_Real: @@ -3529,8 +3885,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, bool FoundConstructor = false; unsigned FoundTQs; - DeclContext::lookup_const_result R = Self.LookupConstructors(RD); - for (DeclContext::lookup_const_iterator Con = R.begin(), + DeclContext::lookup_result R = Self.LookupConstructors(RD); + for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end(); Con != ConEnd; ++Con) { // A template constructor is never a copy constructor. // FIXME: However, it may actually be selected at the actual overload @@ -3569,8 +3925,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return true; bool FoundConstructor = false; - DeclContext::lookup_const_result R = Self.LookupConstructors(RD); - for (DeclContext::lookup_const_iterator Con = R.begin(), + DeclContext::lookup_result R = Self.LookupConstructors(RD); + for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end(); Con != ConEnd; ++Con) { // FIXME: In C++0x, a constructor template can be a default constructor. if (isa<FunctionTemplateDecl>(*Con)) @@ -5139,7 +5495,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { if (Call == TopCall) continue; - if (CheckCallReturnType(Call->getCallReturnType(), + if (CheckCallReturnType(Call->getCallReturnType(Context), Call->getLocStart(), Call, Call->getDirectCallee())) return ExprError(); @@ -5202,10 +5558,11 @@ static void noteOperatorArrows(Sema &S, } } -ExprResult -Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, - tok::TokenKind OpKind, ParsedType &ObjectType, - bool &MayBePseudoDestructor) { +ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + ParsedType &ObjectType, + bool &MayBePseudoDestructor) { // Since this might be a postfix expression, get rid of ParenListExprs. ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); if (Result.isInvalid()) return ExprError(); @@ -5339,20 +5696,6 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, return Base; } -ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, - Expr *MemExpr) { - SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc); - Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call) - << isa<CXXPseudoDestructorExpr>(MemExpr) - << FixItHint::CreateInsertion(ExpectedLParenLoc, "()"); - - return ActOnCallExpr(/*Scope*/ nullptr, - MemExpr, - /*LPLoc*/ ExpectedLParenLoc, - None, - /*RPLoc*/ ExpectedLParenLoc); -} - static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, tok::TokenKind& OpKind, SourceLocation OpLoc) { if (Base->hasPlaceholderType()) { @@ -5393,8 +5736,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, TypeSourceInfo *ScopeTypeInfo, SourceLocation CCLoc, SourceLocation TildeLoc, - PseudoDestructorTypeStorage Destructed, - bool HasTrailingLParen) { + PseudoDestructorTypeStorage Destructed) { TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); QualType ObjectType; @@ -5482,10 +5824,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, TildeLoc, Destructed); - if (HasTrailingLParen) - return Result; - - return DiagnoseDtorReference(Destructed.getLocation(), Result); + return Result; } ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, @@ -5495,8 +5834,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, UnqualifiedId &FirstTypeName, SourceLocation CCLoc, SourceLocation TildeLoc, - UnqualifiedId &SecondTypeName, - bool HasTrailingLParen) { + UnqualifiedId &SecondTypeName) { assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) && "Invalid first type name in pseudo-destructor"); @@ -5623,15 +5961,14 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS, ScopeTypeInfo, CCLoc, TildeLoc, - Destructed, HasTrailingLParen); + Destructed); } ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation TildeLoc, - const DeclSpec& DS, - bool HasTrailingLParen) { + const DeclSpec& DS) { QualType ObjectType; if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) return ExprError(); @@ -5647,7 +5984,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(), nullptr, SourceLocation(), TildeLoc, - Destructed, HasTrailingLParen); + Destructed); } ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, @@ -5685,10 +6022,9 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, if (Exp.isInvalid()) return true; - MemberExpr *ME = - new (Context) MemberExpr(Exp.get(), /*IsArrow=*/false, Method, - SourceLocation(), Context.BoundMemberTy, - VK_RValue, OK_Ordinary); + MemberExpr *ME = new (Context) MemberExpr( + Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(), + Context.BoundMemberTy, VK_RValue, OK_Ordinary); if (HadMultipleCandidates) ME->setHadMultipleCandidates(true); MarkMemberReferenced(ME); @@ -6052,6 +6388,8 @@ public: class TransformTypos : public TreeTransform<TransformTypos> { typedef TreeTransform<TransformTypos> BaseTransform; + VarDecl *InitDecl; // A decl to avoid as a correction because it is in the + // process of being initialized. llvm::function_ref<ExprResult(Expr *)> ExprFilter; llvm::SmallSetVector<TypoExpr *, 2> TypoExprs, AmbiguousTypoExprs; llvm::SmallDenseMap<TypoExpr *, ExprResult, 2> TransformCache; @@ -6130,8 +6468,8 @@ class TransformTypos : public TreeTransform<TransformTypos> { } public: - TransformTypos(Sema &SemaRef, llvm::function_ref<ExprResult(Expr *)> Filter) - : BaseTransform(SemaRef), ExprFilter(Filter) {} + TransformTypos(Sema &SemaRef, VarDecl *InitDecl, llvm::function_ref<ExprResult(Expr *)> Filter) + : BaseTransform(SemaRef), InitDecl(InitDecl), ExprFilter(Filter) {} ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc, MultiExprArg Args, @@ -6210,6 +6548,8 @@ public: // For the first TypoExpr and an uncached TypoExpr, find the next likely // typo correction and return it. while (TypoCorrection TC = State.Consumer->getNextCorrection()) { + if (InitDecl && TC.getCorrectionDecl() == InitDecl) + continue; ExprResult NE = State.RecoveryHandler ? State.RecoveryHandler(SemaRef, E, TC) : attemptRecovery(SemaRef, *State.Consumer, TC); @@ -6234,8 +6574,9 @@ public: }; } -ExprResult Sema::CorrectDelayedTyposInExpr( - Expr *E, llvm::function_ref<ExprResult(Expr *)> Filter) { +ExprResult +Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl, + llvm::function_ref<ExprResult(Expr *)> Filter) { // If the current evaluation context indicates there are uncorrected typos // and the current expression isn't guaranteed to not have typos, try to // resolve any TypoExpr nodes that might be in the expression. @@ -6246,7 +6587,7 @@ ExprResult Sema::CorrectDelayedTyposInExpr( assert(TyposInContext < ~0U && "Recursive call of CorrectDelayedTyposInExpr"); ExprEvalContexts.back().NumTypos = ~0U; auto TyposResolved = DelayedTypos.size(); - auto Result = TransformTypos(*this, Filter).Transform(E); + auto Result = TransformTypos(*this, InitDecl, Filter).Transform(E); ExprEvalContexts.back().NumTypos = TyposInContext; TyposResolved -= DelayedTypos.size(); if (Result.isInvalid() || Result.get() != E) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp index af1cf90..e421349 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp @@ -109,9 +109,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, NamedDecl *D = *I; if (D->isCXXInstanceMember()) { - if (dyn_cast<FieldDecl>(D) || dyn_cast<MSPropertyDecl>(D) - || dyn_cast<IndirectFieldDecl>(D)) - isField = true; + isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || + isa<IndirectFieldDecl>(D); CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); Classes.insert(R->getCanonicalDecl()); @@ -732,8 +731,8 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, static ExprResult BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, - const CXXScopeSpec &SS, FieldDecl *Field, - DeclAccessPair FoundDecl, + SourceLocation OpLoc, const CXXScopeSpec &SS, + FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo); ExprResult @@ -820,10 +819,10 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, // Make a nameInfo that properly uses the anonymous name. DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); - + result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer, - EmptySS, field, foundDecl, - memberNameInfo).get(); + SourceLocation(), EmptySS, field, + foundDecl, memberNameInfo).get(); if (!result) return ExprError(); @@ -841,9 +840,10 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, DeclAccessPair fakeFoundDecl = DeclAccessPair::make(field, field->getAccess()); - result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false, - (FI == FEnd? SS : EmptySS), field, - fakeFoundDecl, memberNameInfo).get(); + result = + BuildFieldReferenceExpr(*this, result, /*isarrow*/ false, + SourceLocation(), (FI == FEnd ? SS : EmptySS), + field, fakeFoundDecl, memberNameInfo).get(); } return result; @@ -863,18 +863,16 @@ BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow, } /// \brief Build a MemberExpr AST node. -static MemberExpr * -BuildMemberExpr(Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow, - const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - ValueDecl *Member, DeclAccessPair FoundDecl, - const DeclarationNameInfo &MemberNameInfo, QualType Ty, - ExprValueKind VK, ExprObjectKind OK, - const TemplateArgumentListInfo *TemplateArgs = nullptr) { +static MemberExpr *BuildMemberExpr( + Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow, + SourceLocation OpLoc, const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + ValueDecl *Member, DeclAccessPair FoundDecl, + const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, + ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr) { assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue"); - MemberExpr *E = - MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), - TemplateKWLoc, Member, FoundDecl, MemberNameInfo, - TemplateArgs, Ty, VK, OK); + MemberExpr *E = MemberExpr::Create( + C, Base, isArrow, OpLoc, SS.getWithLocInContext(C), TemplateKWLoc, Member, + FoundDecl, MemberNameInfo, TemplateArgs, Ty, VK, OK); SemaRef.MarkMemberReferenced(E); return E; } @@ -969,8 +967,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, CXXScopeSpec TempSS(SS); RetryExpr = ActOnMemberAccessExpr( ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS, - TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl, - ExtraArgs->HasTrailingLParen); + TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl); } if (Trap.hasErrorOccurred()) RetryExpr = ExprError(); @@ -1058,8 +1055,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return ExprError(); if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) - return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, - SS, FD, FoundDecl, MemberNameInfo); + return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, OpLoc, SS, FD, + FoundDecl, MemberNameInfo); if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl)) return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD, @@ -1073,8 +1070,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, OpLoc); if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { - return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc, - Var, FoundDecl, MemberNameInfo, + return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS, + TemplateKWLoc, Var, FoundDecl, MemberNameInfo, Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary); } @@ -1090,16 +1087,16 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, type = MemberFn->getType(); } - return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc, - MemberFn, FoundDecl, MemberNameInfo, type, valueKind, - OK_Ordinary); + return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS, + TemplateKWLoc, MemberFn, FoundDecl, MemberNameInfo, + type, valueKind, OK_Ordinary); } assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { - return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, TemplateKWLoc, - Enum, FoundDecl, MemberNameInfo, Enum->getType(), - VK_RValue, OK_Ordinary); + return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS, + TemplateKWLoc, Enum, FoundDecl, MemberNameInfo, + Enum->getType(), VK_RValue, OK_Ordinary); } // We found something that we didn't expect. Complain. @@ -1521,7 +1518,15 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, if (BaseType->isExtVectorType()) { // FIXME: this expr should store IsArrow. IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); - ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind()); + ExprValueKind VK; + if (IsArrow) + VK = VK_LValue; + else { + if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(BaseExpr.get())) + VK = POE->getSyntacticForm()->getValueKind(); + else + VK = BaseExpr.get()->getValueKind(); + } QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc, Member, MemberLoc); if (ret.isNull()) @@ -1591,9 +1596,6 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, /// possibilities, including destructor and operator references. /// /// \param OpKind either tok::arrow or tok::period -/// \param HasTrailingLParen whether the next token is '(', which -/// is used to diagnose mis-uses of special members that can -/// only be called /// \param ObjCImpDecl the current Objective-C \@implementation /// decl; this is an ugly hack around the fact that Objective-C /// \@implementations aren't properly put in the context chain @@ -1603,24 +1605,10 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, - Decl *ObjCImpDecl, - bool HasTrailingLParen) { + Decl *ObjCImpDecl) { if (SS.isSet() && SS.isInvalid()) return ExprError(); - // The only way a reference to a destructor can be used is to - // immediately call it. If the next token is not a '(', produce - // a diagnostic and build the call now. - if (!HasTrailingLParen && - Id.getKind() == UnqualifiedId::IK_DestructorName) { - ExprResult DtorAccess = - ActOnMemberAccessExpr(S, Base, OpLoc, OpKind, SS, TemplateKWLoc, Id, - ObjCImpDecl, /*HasTrailingLParen*/true); - if (DtorAccess.isInvalid()) - return DtorAccess; - return DiagnoseDtorReference(Id.getLocStart(), DtorAccess.get()); - } - // Warn about the explicit constructor calls Microsoft extension. if (getLangOpts().MicrosoftExt && Id.getKind() == UnqualifiedId::IK_ConstructorName) @@ -1653,8 +1641,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, NameInfo, TemplateArgs); } - ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl, - HasTrailingLParen}; + ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs, &ExtraArgs); @@ -1662,8 +1649,8 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, static ExprResult BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, - const CXXScopeSpec &SS, FieldDecl *Field, - DeclAccessPair FoundDecl, + SourceLocation OpLoc, const CXXScopeSpec &SS, + FieldDecl *Field, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo) { // x.a is an l-value if 'a' has a reference type. Otherwise: // x.a is an l-value/x-value/pr-value if the base is (and note @@ -1716,7 +1703,7 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, FoundDecl, Field); if (Base.isInvalid()) return ExprError(); - return BuildMemberExpr(S, S.Context, Base.get(), IsArrow, SS, + return BuildMemberExpr(S, S.Context, Base.get(), IsArrow, OpLoc, SS, /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, MemberNameInfo, MemberType, VK, OK); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index 9c3b51c..63b7485 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -218,7 +218,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, S.Diag(Loc, diag::err_undeclared_nsnumber); return nullptr; } - + } + + if (S.NSNumberPointer.isNull()) { // generate the pointer to NSNumber type. QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl); S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject); @@ -1041,7 +1043,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, SourceLocation RParenLoc, bool WarnMultipleSelectors) { ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, - SourceRange(LParenLoc, RParenLoc), false, false); + SourceRange(LParenLoc, RParenLoc)); if (!Method) Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(LParenLoc, RParenLoc)); @@ -1059,15 +1061,11 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, } else DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc, WarnMultipleSelectors); - + if (Method && Method->getImplementationControl() != ObjCMethodDecl::Optional && - !getSourceManager().isInSystemHeader(Method->getLocation())) { - llvm::DenseMap<Selector, SourceLocation>::iterator Pos - = ReferencedSelectors.find(Sel); - if (Pos == ReferencedSelectors.end()) - ReferencedSelectors.insert(std::make_pair(Sel, AtLoc)); - } + !getSourceManager().isInSystemHeader(Method->getLocation())) + ReferencedSelectors.insert(std::make_pair(Sel, AtLoc)); // In ARC, forbid the user from using @selector for // retain/release/autorelease/dealloc/retainCount. @@ -1507,64 +1505,6 @@ ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, return nullptr; } -static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) { - if (!Receiver) - return; - - if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Receiver)) - Receiver = OVE->getSourceExpr(); - - Expr *RExpr = Receiver->IgnoreParenImpCasts(); - SourceLocation Loc = RExpr->getLocStart(); - QualType T = RExpr->getType(); - const ObjCPropertyDecl *PDecl = nullptr; - const ObjCMethodDecl *GDecl = nullptr; - if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) { - RExpr = POE->getSyntacticForm(); - if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) { - if (PRE->isImplicitProperty()) { - GDecl = PRE->getImplicitPropertyGetter(); - if (GDecl) { - T = GDecl->getReturnType(); - } - } - else { - PDecl = PRE->getExplicitProperty(); - if (PDecl) { - T = PDecl->getType(); - } - } - } - } - else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RExpr)) { - // See if receiver is a method which envokes a synthesized getter - // backing a 'weak' property. - ObjCMethodDecl *Method = ME->getMethodDecl(); - if (Method && Method->getSelector().getNumArgs() == 0) { - PDecl = Method->findPropertyDecl(); - if (PDecl) - T = PDecl->getType(); - } - } - - if (T.getObjCLifetime() != Qualifiers::OCL_Weak) { - if (!PDecl) - return; - if (!(PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)) - return; - } - - S.Diag(Loc, diag::warn_receiver_is_weak) - << ((!PDecl && !GDecl) ? 0 : (PDecl ? 1 : 2)); - - if (PDecl) - S.Diag(PDecl->getLocation(), diag::note_property_declare); - else if (GDecl) - S.Diag(GDecl->getLocation(), diag::note_method_declared_at) << GDecl; - - S.Diag(Loc, diag::note_arc_assign_to_strong); -} - /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. ExprResult Sema:: @@ -1751,29 +1691,30 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, IsSuper = true; if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) { - if (CurMethod->isInstanceMethod()) { - ObjCInterfaceDecl *Super = - CurMethod->getClassInterface()->getSuperClass(); - if (!Super) { - // The current class does not have a superclass. - Diag(receiverNameLoc, diag::error_root_class_cannot_use_super) - << CurMethod->getClassInterface()->getIdentifier(); - return ExprError(); + if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) { + if (CurMethod->isInstanceMethod()) { + ObjCInterfaceDecl *Super = Class->getSuperClass(); + if (!Super) { + // The current class does not have a superclass. + Diag(receiverNameLoc, diag::error_root_class_cannot_use_super) + << Class->getIdentifier(); + return ExprError(); + } + QualType T = Context.getObjCInterfaceType(Super); + T = Context.getObjCObjectPointerType(T); + + return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), + /*BaseExpr*/nullptr, + SourceLocation()/*OpLoc*/, + &propertyName, + propertyNameLoc, + receiverNameLoc, T, true); } - QualType T = Context.getObjCInterfaceType(Super); - T = Context.getObjCObjectPointerType(T); - - return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), - /*BaseExpr*/nullptr, - SourceLocation()/*OpLoc*/, - &propertyName, - propertyNameLoc, - receiverNameLoc, T, true); - } - // Otherwise, if this is a class method, try dispatching to our - // superclass. - IFace = CurMethod->getClassInterface()->getSuperClass(); + // Otherwise, if this is a class method, try dispatching to our + // superclass. + IFace = Class->getSuperClass(); + } } } @@ -2452,8 +2393,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (ObjCMethodDecl *BestMethod = SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod())) Method = BestMethod; - if (!AreMultipleMethodsInGlobalPool(Sel, Method->isInstanceMethod())) + if (!AreMultipleMethodsInGlobalPool(Sel, Method, + SourceRange(LBracLoc, RBracLoc), + receiverIsId)) { DiagnoseUseOfDecl(Method, SelLoc); + } } } else if (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()) { @@ -2491,14 +2435,12 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // If not messaging 'self', look for any factory method named 'Sel'. if (!Receiver || !isSelfExpr(Receiver)) { Method = LookupFactoryMethodInGlobalPool(Sel, - SourceRange(LBracLoc, RBracLoc), - true); + SourceRange(LBracLoc, RBracLoc)); 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); + SourceRange(LBracLoc, RBracLoc)); if (Method) if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) { @@ -2575,6 +2517,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (OCIType->qual_empty()) { Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc)); + if (Method) { + if (auto BestMethod = + SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod())) + Method = BestMethod; + AreMultipleMethodsInGlobalPool(Sel, Method, + SourceRange(LBracLoc, RBracLoc), + true); + } if (Method && !forwardClass) Diag(SelLoc, diag::warn_maynot_respond) << OCIType->getInterfaceDecl()->getIdentifier() @@ -2757,15 +2707,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } if (getLangOpts().ObjCAutoRefCount) { - // Do not warn about IBOutlet weak property receivers being set to null - // as this cannot asynchronously happen. - bool WarnWeakReceiver = true; - if (isImplicit && Method) - if (const ObjCPropertyDecl *PropertyDecl = Method->findPropertyDecl()) - WarnWeakReceiver = !PropertyDecl->hasAttr<IBOutletAttr>(); - if (WarnWeakReceiver) - DiagnoseARCUseOfWeakReceiver(*this, Receiver); - // In ARC, annotate delegate init calls. if (Result->getMethodFamily() == OMF_init && (SuperLoc.isValid() || isSelfExpr(Receiver))) { @@ -2796,7 +2737,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } } - + + CheckObjCCircularContainer(Result); + return MaybeBindToTemporary(Result); } @@ -2805,8 +2748,7 @@ static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) { dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) { Selector Sel = OSE->getSelector(); SourceLocation Loc = OSE->getAtLoc(); - llvm::DenseMap<Selector, SourceLocation>::iterator Pos - = S.ReferencedSelectors.find(Sel); + auto Pos = S.ReferencedSelectors.find(Sel); if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc) S.ReferencedSelectors.erase(Pos); } @@ -3028,17 +2970,20 @@ namespace { /// Some declaration references are okay. ACCResult VisitDeclRefExpr(DeclRefExpr *e) { - // References to global constants from system headers are okay. - // These are things like 'kCFStringTransformToLatin'. They are - // can also be assumed to be immune to retains. VarDecl *var = dyn_cast<VarDecl>(e->getDecl()); + // References to global constants are okay. if (isAnyRetainable(TargetClass) && isAnyRetainable(SourceClass) && var && var->getStorageClass() == SC_Extern && - var->getType().isConstQualified() && - Context.getSourceManager().isInSystemHeader(var->getLocation())) { - return ACC_bottom; + var->getType().isConstQualified()) { + + // In system headers, they can also be assumed to be immune to retains. + // These are things like 'kCFStringTransformToLatin'. + if (Context.getSourceManager().isInSystemHeader(var->getLocation())) + return ACC_bottom; + + return ACC_plusZero; } // Nothing else. @@ -3421,7 +3366,7 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr, ObjCInterfaceDecl *CastClass = InterfacePointerType->getObjectType()->getInterface(); if ((CastClass == ExprClass) || - (CastClass && ExprClass->isSuperClassOf(CastClass))) + (CastClass && CastClass->isSuperClassOf(ExprClass))) return true; if (warn) S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) @@ -3444,12 +3389,13 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr, return false; } } + } else if (!castType->isObjCIdType()) { + S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface) + << castExpr->getType() << Parm; + S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); + if (Target) + S.Diag(Target->getLocStart(), diag::note_declared_at); } - S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface) - << castExpr->getType() << Parm; - S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); - if (Target) - S.Diag(Target->getLocStart(), diag::note_declared_at); return true; } return false; @@ -3469,6 +3415,9 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr, if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) { if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) { HadTheAttribute = true; + if (Parm->isStr("id")) + return true; + NamedDecl *Target = nullptr; // Check for an existing type with this name. LookupResult R(S, DeclarationName(Parm), SourceLocation(), diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp index 32b56bc..2e327ec 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp @@ -161,11 +161,8 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr, } static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name) { - const IdentifierInfo *II = &S.getASTContext().Idents.get(Name); - if (!II->hadMacroDefinition()) return false; - - MacroDirective *Macro = S.PP.getMacroDirectiveHistory(II); - return Macro && Macro->findDirectiveAtLoc(Loc, S.getSourceManager()); + return (bool)S.PP.getMacroDefinitionAtLoc(&S.getASTContext().Idents.get(Name), + Loc); } static std::string getScalarZeroExpressionForType( diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index 2ad6754..610e0a9 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -150,7 +150,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, Sema &S) { // Get the length of the string as parsed. auto *ConstantArrayTy = - cast<ConstantArrayType>(Str->getType()->getUnqualifiedDesugaredType()); + cast<ConstantArrayType>(Str->getType()->getAsArrayTypeUnsafe()); uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue(); if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) { @@ -640,6 +640,9 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, bool VerifyOnly) : SemaRef(S), VerifyOnly(VerifyOnly) { + // FIXME: Check that IL isn't already the semantic form of some other + // InitListExpr. If it is, we'd create a broken AST. + hadError = false; FullyStructuredList = @@ -751,6 +754,68 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, } } +/// Warn that \p Entity was of scalar type and was initialized by a +/// single-element braced initializer list. +static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, + SourceRange Braces) { + // Don't warn during template instantiation. If the initialization was + // non-dependent, we warned during the initial parse; otherwise, the + // type might not be scalar in some uses of the template. + if (!S.ActiveTemplateInstantiations.empty()) + return; + + unsigned DiagID = 0; + + switch (Entity.getKind()) { + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Parameter_CF_Audited: + case InitializedEntity::EK_Result: + // Extra braces here are suspicious. + DiagID = diag::warn_braces_around_scalar_init; + break; + + case InitializedEntity::EK_Member: + // Warn on aggregate initialization but not on ctor init list or + // default member initializer. + if (Entity.getParent()) + DiagID = diag::warn_braces_around_scalar_init; + break; + + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_LambdaCapture: + // No warning, might be direct-list-initialization. + // FIXME: Should we warn for copy-list-initialization in these cases? + break; + + case InitializedEntity::EK_New: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_CompoundLiteralInit: + // No warning, braces are part of the syntax of the underlying construct. + break; + + case InitializedEntity::EK_RelatedResult: + // No warning, we already warned when initializing the result. + break; + + case InitializedEntity::EK_Exception: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + case InitializedEntity::EK_BlockElement: + llvm_unreachable("unexpected braced scalar init"); + } + + if (DiagID) { + S.Diag(Braces.getBegin(), DiagID) + << Braces + << FixItHint::CreateRemoval(Braces.getBegin()) + << FixItHint::CreateRemoval(Braces.getEnd()); + } +} + + /// Check whether the initializer \p IList (that was written with explicit /// braces) can be used to initialize an object of type \p T. /// @@ -826,12 +891,9 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, } } - if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 && - !TopLevelObject) - SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init) - << IList->getSourceRange() - << FixItHint::CreateRemoval(IList->getLocStart()) - << FixItHint::CreateRemoval(IList->getLocEnd()); + if (!VerifyOnly && T->isScalarType() && + IList->getNumInits() == 1 && !isa<InitListExpr>(IList->getInit(0))) + warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange()); } void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, @@ -904,7 +966,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, StructuredList, StructuredIndex); if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) { - if (!ElemType->isRecordType() || ElemType->isAggregateType()) { + if (!SemaRef.getLangOpts().CPlusPlus) { InitListExpr *InnerStructuredList = getStructuredSubobjectInit(IList, Index, ElemType, StructuredList, StructuredIndex, @@ -915,8 +977,6 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, ++Index; return; } - assert(SemaRef.getLangOpts().CPlusPlus && - "non-aggregate records are only possible in C++"); // C++ initialization is handled later. } else if (isa<ImplicitValueInitExpr>(expr)) { // This happens during template instantiation when we see an InitListExpr @@ -929,43 +989,24 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, return; } - // FIXME: Need to handle atomic aggregate types with implicit init lists. - if (ElemType->isScalarType() || ElemType->isAtomicType()) - return CheckScalarType(Entity, IList, ElemType, Index, - StructuredList, StructuredIndex); - - assert((ElemType->isRecordType() || ElemType->isVectorType() || - ElemType->isArrayType()) && "Unexpected type"); - - if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) { - // arrayType can be incomplete if we're initializing a flexible - // array member. There's nothing we can do with the completed - // type here, though. - - if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) { - if (!VerifyOnly) { - CheckStringInit(expr, ElemType, arrayType, SemaRef); - UpdateStructuredListElement(StructuredList, StructuredIndex, expr); - } - ++Index; - return; - } - - // Fall through for subaggregate initialization. - - } else if (SemaRef.getLangOpts().CPlusPlus) { - // C++ [dcl.init.aggr]p12: - // All implicit type conversions (clause 4) are considered when - // initializing the aggregate member with an initializer from - // an initializer-list. If the initializer can initialize a - // member, the member is initialized. [...] + if (SemaRef.getLangOpts().CPlusPlus) { + // C++ [dcl.init.aggr]p2: + // Each member is copy-initialized from the corresponding + // initializer-clause. // FIXME: Better EqualLoc? InitializationKind Kind = InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); - InitializationSequence Seq(SemaRef, Entity, Kind, expr); + InitializationSequence Seq(SemaRef, Entity, Kind, expr, + /*TopLevelOfInitList*/ true); - if (Seq) { + // C++14 [dcl.init.aggr]p13: + // If the assignment-expression can initialize a member, the member is + // initialized. Otherwise [...] brace elision is assumed + // + // Brace elision is never performed if the element is not an + // assignment-expression. + if (Seq || isa<InitListExpr>(expr)) { if (!VerifyOnly) { ExprResult Result = Seq.Perform(SemaRef, Entity, Kind, expr); @@ -974,13 +1015,38 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, UpdateStructuredListElement(StructuredList, StructuredIndex, Result.getAs<Expr>()); - } + } else if (!Seq) + hadError = true; ++Index; return; } // Fall through for subaggregate initialization + } else if (ElemType->isScalarType() || ElemType->isAtomicType()) { + // FIXME: Need to handle atomic aggregate types with implicit init lists. + return CheckScalarType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); + } else if (const ArrayType *arrayType = + SemaRef.Context.getAsArrayType(ElemType)) { + // arrayType can be incomplete if we're initializing a flexible + // array member. There's nothing we can do with the completed + // type here, though. + + if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) { + if (!VerifyOnly) { + CheckStringInit(expr, ElemType, arrayType, SemaRef); + UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + } + ++Index; + return; + } + + // Fall through for subaggregate initialization. + } else { + assert((ElemType->isRecordType() || ElemType->isVectorType()) && + "Unexpected type"); + // C99 6.7.8p13: // // The initializer for a structure or union object that has @@ -990,10 +1056,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // initial value of the object, including unnamed members, is // that of the expression. ExprResult ExprRes = expr; - if ((ElemType->isRecordType() || ElemType->isVectorType()) && - SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes, - !VerifyOnly) - != Sema::Incompatible) { + if (SemaRef.CheckSingleAssignmentConstraints( + ElemType, ExprRes, !VerifyOnly) != Sema::Incompatible) { if (ExprRes.isInvalid()) hadError = true; else { @@ -3037,6 +3101,28 @@ void InitializationSequence::SetOverloadFailure(FailureKind Failure, // Attempt initialization //===----------------------------------------------------------------------===// +/// Tries to add a zero initializer. Returns true if that worked. +static bool +maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence, + const InitializedEntity &Entity) { + if (Entity.getKind() != InitializedEntity::EK_Variable) + return false; + + VarDecl *VD = cast<VarDecl>(Entity.getDecl()); + if (VD->getInit() || VD->getLocEnd().isMacroID()) + return false; + + QualType VariableTy = VD->getType().getCanonicalType(); + SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd()); + std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); + if (!Init.empty()) { + Sequence.AddZeroInitializationStep(Entity.getType()); + Sequence.SetZeroInitializationFixit(Init, Loc); + return true; + } + return false; +} + static void MaybeProduceObjCObject(Sema &S, InitializationSequence &Sequence, const InitializedEntity &Entity) { @@ -3107,15 +3193,13 @@ static OverloadingResult ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, MultiExprArg Args, OverloadCandidateSet &CandidateSet, - ArrayRef<NamedDecl *> Ctors, + DeclContext::lookup_result Ctors, OverloadCandidateSet::iterator &Best, bool CopyInitializing, bool AllowExplicit, - bool OnlyListConstructors, bool InitListSyntax) { + bool OnlyListConstructors, bool IsListInit) { CandidateSet.clear(); - for (ArrayRef<NamedDecl *>::iterator - Con = Ctors.begin(), ConEnd = Ctors.end(); Con != ConEnd; ++Con) { - NamedDecl *D = *Con; + for (NamedDecl *D : Ctors) { DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); bool SuppressUserConversions = false; @@ -3129,19 +3213,21 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, Constructor = cast<CXXConstructorDecl>(D); // C++11 [over.best.ics]p4: - // However, when considering the argument of a constructor or - // user-defined conversion function that is a candidate: - // -- by 13.3.1.3 when invoked for the copying/moving of a temporary - // in the second step of a class copy-initialization, - // -- by 13.3.1.7 when passing the initializer list as a single - // argument or when the initializer list has exactly one elementand - // a conversion to some class X or reference to (possibly - // cv-qualified) X is considered for the first parameter of a - // constructor of X, or - // -- by 13.3.1.4, 13.3.1.5, or 13.3.1.6 in all cases, - // only standard conversion sequences and ellipsis conversion sequences - // are considered. - if ((CopyInitializing || (InitListSyntax && Args.size() == 1)) && + // ... and the constructor or user-defined conversion function is a + // candidate by + // - 13.3.1.3, when the argument is the temporary in the second step + // of a class copy-initialization, or + // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), + // user-defined conversion sequences are not considered. + // FIXME: This breaks backward compatibility, e.g. PR12117. As a + // temporary fix, let's re-instate the third bullet above until + // there is a resolution in the standard, i.e., + // - 13.3.1.7 when the initializer list has exactly one element that is + // itself an initializer list and a conversion to some class X or + // reference to (possibly cv-qualified) X is considered for the first + // parameter of a constructor of X. + if ((CopyInitializing || + (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]))) && Constructor->isCopyOrMoveConstructor()) SuppressUserConversions = true; } @@ -3178,16 +3264,19 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, /// \brief Attempt initialization by constructor (C++ [dcl.init]), which /// enumerates the constructors of the initialized entity and performs overload /// resolution to select the best. -/// If InitListSyntax is true, this is list-initialization of a non-aggregate -/// class type. +/// \param IsListInit Is this list-initialization? +/// \param IsInitListCopy Is this non-list-initialization resulting from a +/// list-initialization from {x} where x is the same +/// type as the entity? static void TryConstructorInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType DestType, InitializationSequence &Sequence, - bool InitListSyntax = false) { - assert((!InitListSyntax || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) && - "InitListSyntax must come with a single initializer list argument."); + bool IsListInit = false, + bool IsInitListCopy = false) { + assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) && + "IsListInit must come with a single initializer list argument."); // The type we're constructing needs to be complete. if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { @@ -3206,29 +3295,28 @@ static void TryConstructorInitialization(Sema &S, // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. - bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax; + bool AllowExplicit = Kind.AllowExplicit() || IsListInit; bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy; // - Otherwise, if T is a class type, constructors are considered. The // applicable constructors are enumerated, and the best one is chosen // through overload resolution. - DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl); - // The container holding the constructors can under certain conditions - // be changed while iterating (e.g. because of deserialization). - // To be safe we copy the lookup results to a new container. - SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end()); + DeclContext::lookup_result Ctors = S.LookupConstructors(DestRecordDecl); OverloadingResult Result = OR_No_Viable_Function; OverloadCandidateSet::iterator Best; bool AsInitializerList = false; - // C++11 [over.match.list]p1: - // When objects of non-aggregate type T are list-initialized, overload - // resolution selects the constructor in two phases: + // C++11 [over.match.list]p1, per DR1467: + // When objects of non-aggregate type T are list-initialized, such that + // 8.5.4 [dcl.init.list] specifies that overload resolution is performed + // according to the rules in this section, overload resolution selects + // the constructor in two phases: + // // - Initially, the candidate functions are the initializer-list // constructors of the class T and the argument list consists of the // initializer list as a single argument. - if (InitListSyntax) { + if (IsListInit) { InitListExpr *ILE = cast<InitListExpr>(Args[0]); AsInitializerList = true; @@ -3239,7 +3327,7 @@ static void TryConstructorInitialization(Sema &S, CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructor=*/true, - InitListSyntax); + IsListInit); // Time to unwrap the init list. Args = MultiExprArg(ILE->getInits(), ILE->getNumInits()); @@ -3256,10 +3344,10 @@ static void TryConstructorInitialization(Sema &S, CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructors=*/false, - InitListSyntax); + IsListInit); } if (Result) { - Sequence.SetOverloadFailure(InitListSyntax ? + Sequence.SetOverloadFailure(IsListInit ? InitializationSequence::FK_ListConstructorOverloadFailed : InitializationSequence::FK_ConstructorOverloadFailed, Result); @@ -3273,7 +3361,8 @@ static void TryConstructorInitialization(Sema &S, if (Kind.getKind() == InitializationKind::IK_Default && Entity.getType().isConstQualified() && !cast<CXXConstructorDecl>(Best->Function)->isUserProvided()) { - Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); return; } @@ -3281,7 +3370,7 @@ static void TryConstructorInitialization(Sema &S, // In copy-list-initialization, if an explicit constructor is chosen, the // initializer is ill-formed. CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); - if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { + if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); return; } @@ -3289,10 +3378,9 @@ static void TryConstructorInitialization(Sema &S, // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. bool HadMultipleCandidates = (CandidateSet.size() > 1); - Sequence.AddConstructorInitializationStep(CtorDecl, - Best->FoundDecl.getAccess(), - DestType, HadMultipleCandidates, - InitListSyntax, AsInitializerList); + Sequence.AddConstructorInitializationStep( + CtorDecl, Best->FoundDecl.getAccess(), DestType, HadMultipleCandidates, + IsListInit | IsInitListCopy, AsInitializerList); } static bool @@ -3350,6 +3438,11 @@ static void TryReferenceListInitialization(Sema &S, Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); return; } + // Can't reference initialize a compound literal. + if (Entity.getKind() == InitializedEntity::EK_CompoundLiteralInit) { + Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); + return; + } QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); @@ -3425,48 +3518,97 @@ static void TryListInitialization(Sema &S, TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence); return; } - if (DestType->isRecordType()) { - if (S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) { - Sequence.setIncompleteTypeFailure(DestType); - return; - } - // C++11 [dcl.init.list]p3: - // - If T is an aggregate, aggregate initialization is performed. - if (!DestType->isAggregateType()) { - if (S.getLangOpts().CPlusPlus11) { - // - Otherwise, if the initializer list has no elements and T is a - // class type with a default constructor, the object is - // value-initialized. - if (InitList->getNumInits() == 0) { - CXXRecordDecl *RD = DestType->getAsCXXRecordDecl(); - if (RD->hasDefaultConstructor()) { - TryValueInitialization(S, Entity, Kind, Sequence, InitList); - return; - } + if (DestType->isRecordType() && + S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) { + Sequence.setIncompleteTypeFailure(DestType); + return; + } + + // C++11 [dcl.init.list]p3, per DR1467: + // - If T is a class type and the initializer list has a single element of + // type cv U, where U is T or a class derived from T, the object is + // initialized from that element (by copy-initialization for + // copy-list-initialization, or by direct-initialization for + // direct-list-initialization). + // - Otherwise, if T is a character array and the initializer list has a + // single element that is an appropriately-typed string literal + // (8.5.2 [dcl.init.string]), initialization is performed as described + // in that section. + // - Otherwise, if T is an aggregate, [...] (continue below). + if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1) { + if (DestType->isRecordType()) { + QualType InitType = InitList->getInit(0)->getType(); + if (S.Context.hasSameUnqualifiedType(InitType, DestType) || + S.IsDerivedFrom(InitType, DestType)) { + Expr *InitAsExpr = InitList->getInit(0); + TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType, + Sequence, /*InitListSyntax*/ false, + /*IsInitListCopy*/ true); + return; + } + } + if (const ArrayType *DestAT = S.Context.getAsArrayType(DestType)) { + Expr *SubInit[1] = {InitList->getInit(0)}; + if (!isa<VariableArrayType>(DestAT) && + IsStringInit(SubInit[0], DestAT, S.Context) == SIF_None) { + InitializationKind SubKind = + Kind.getKind() == InitializationKind::IK_DirectList + ? InitializationKind::CreateDirect(Kind.getLocation(), + InitList->getLBraceLoc(), + InitList->getRBraceLoc()) + : Kind; + Sequence.InitializeFrom(S, Entity, SubKind, SubInit, + /*TopLevelOfInitList*/ true); + + // TryStringLiteralInitialization() (in InitializeFrom()) will fail if + // the element is not an appropriately-typed string literal, in which + // case we should proceed as in C++11 (below). + if (Sequence) { + Sequence.RewrapReferenceInitList(Entity.getType(), InitList); + return; } + } + } + } - // - Otherwise, if T is a specialization of std::initializer_list<E>, - // an initializer_list object constructed [...] - if (TryInitializerListConstruction(S, InitList, DestType, Sequence)) + // C++11 [dcl.init.list]p3: + // - If T is an aggregate, aggregate initialization is performed. + if (DestType->isRecordType() && !DestType->isAggregateType()) { + if (S.getLangOpts().CPlusPlus11) { + // - Otherwise, if the initializer list has no elements and T is a + // class type with a default constructor, the object is + // value-initialized. + if (InitList->getNumInits() == 0) { + CXXRecordDecl *RD = DestType->getAsCXXRecordDecl(); + if (RD->hasDefaultConstructor()) { + TryValueInitialization(S, Entity, Kind, Sequence, InitList); return; + } + } - // - Otherwise, if T is a class type, constructors are considered. - Expr *InitListAsExpr = InitList; - TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, - Sequence, /*InitListSyntax*/true); - } else - Sequence.SetFailed( - InitializationSequence::FK_InitListBadDestinationType); - return; - } + // - Otherwise, if T is a specialization of std::initializer_list<E>, + // an initializer_list object constructed [...] + if (TryInitializerListConstruction(S, InitList, DestType, Sequence)) + return; + + // - Otherwise, if T is a class type, constructors are considered. + Expr *InitListAsExpr = InitList; + TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, + Sequence, /*InitListSyntax*/ true); + } else + Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType); + return; } + if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() && InitList->getNumInits() == 1 && InitList->getInit(0)->getType()->isRecordType()) { // - Otherwise, if the initializer list has a single element of type E // [...references are handled above...], the object or reference is - // initialized from that element; if a narrowing conversion is required + // initialized from that element (by copy-initialization for + // copy-list-initialization, or by direct-initialization for + // direct-list-initialization); if a narrowing conversion is required // to convert the element to T, the program is ill-formed. // // Per core-24034, this is direct-initialization if we were performing @@ -3543,14 +3685,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // to see if there is a suitable conversion. CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl()); - DeclContext::lookup_result R = S.LookupConstructors(T1RecordDecl); - // The container holding the constructors can under certain conditions - // be changed while iterating (e.g. because of deserialization). - // To be safe we copy the lookup results to a new container. - SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end()); - for (SmallVectorImpl<NamedDecl *>::iterator - CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) { - NamedDecl *D = *CI; + for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) { DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); // Find the constructor (which may be a template). @@ -3586,11 +3721,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // functions. CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl()); - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> - Conversions = T2RecordDecl->getVisibleConversionFunctions(); - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { + const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions(); + for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) @@ -4127,7 +4259,8 @@ static void TryDefaultInitialization(Sema &S, // a const-qualified type T, T shall be a class type with a user-provided // default constructor. if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) { - Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); return; } @@ -4218,11 +4351,9 @@ static void TryUserDefinedConversion(Sema &S, CXXRecordDecl *SourceRecordDecl = cast<CXXRecordDecl>(SourceRecordType->getDecl()); - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> - Conversions = SourceRecordDecl->getVisibleConversionFunctions(); - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { + const auto &Conversions = + SourceRecordDecl->getVisibleConversionFunctions(); + for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) @@ -4408,8 +4539,7 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { /// \brief Determine whether we have compatible array types for the /// purposes of GNU by-copy array initialization. -static bool hasCompatibleArrayTypes(ASTContext &Context, - const ArrayType *Dest, +static bool hasCompatibleArrayTypes(ASTContext &Context, const ArrayType *Dest, const ArrayType *Source) { // If the source and destination array types are equivalent, we're // done. @@ -4668,7 +4798,7 @@ void InitializationSequence::InitializeFrom(Sema &S, return; } - // Determine whether we should consider writeback conversions for + // Determine whether we should consider writeback conversions for // Objective-C ARC. bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount && Entity.isParameterKind(); @@ -5022,6 +5152,8 @@ static ExprResult CopyObject(Sema &S, const InitializedEntity &Entity, ExprResult CurInit, bool IsExtraneousCopy) { + if (CurInit.isInvalid()) + return CurInit; // Determine which class type we're copying to. Expr *CurInitExpr = (Expr *)CurInit.get(); CXXRecordDecl *Class = nullptr; @@ -5636,6 +5768,115 @@ static void DiagnoseNarrowingInInitList(Sema &S, QualType EntityType, const Expr *PostInit); +/// Provide warnings when std::move is used on construction. +static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr, + bool IsReturnStmt) { + if (!InitExpr) + return; + + QualType DestType = InitExpr->getType(); + if (!DestType->isRecordType()) + return; + + unsigned DiagID = 0; + if (IsReturnStmt) { + const CXXConstructExpr *CCE = + dyn_cast<CXXConstructExpr>(InitExpr->IgnoreParens()); + if (!CCE || CCE->getNumArgs() != 1) + return; + + if (!CCE->getConstructor()->isCopyOrMoveConstructor()) + return; + + InitExpr = CCE->getArg(0)->IgnoreImpCasts(); + + // Remove implicit temporary and constructor nodes. + if (const MaterializeTemporaryExpr *MTE = + dyn_cast<MaterializeTemporaryExpr>(InitExpr)) { + InitExpr = MTE->GetTemporaryExpr()->IgnoreImpCasts(); + while (const CXXConstructExpr *CCE = + dyn_cast<CXXConstructExpr>(InitExpr)) { + if (isa<CXXTemporaryObjectExpr>(CCE)) + return; + if (CCE->getNumArgs() == 0) + return; + if (CCE->getNumArgs() > 1 && !isa<CXXDefaultArgExpr>(CCE->getArg(1))) + return; + InitExpr = CCE->getArg(0); + } + InitExpr = InitExpr->IgnoreImpCasts(); + DiagID = diag::warn_redundant_move_on_return; + } + } + + // Find the std::move call and get the argument. + const CallExpr *CE = dyn_cast<CallExpr>(InitExpr->IgnoreParens()); + if (!CE || CE->getNumArgs() != 1) + return; + + const FunctionDecl *MoveFunction = CE->getDirectCallee(); + if (!MoveFunction || !MoveFunction->isInStdNamespace() || + !MoveFunction->getIdentifier() || + !MoveFunction->getIdentifier()->isStr("move")) + return; + + const Expr *Arg = CE->getArg(0)->IgnoreImplicit(); + + if (IsReturnStmt) { + const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts()); + if (!DRE || DRE->refersToEnclosingVariableOrCapture()) + return; + + const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); + if (!VD || !VD->hasLocalStorage()) + return; + + if (!VD->getType()->isRecordType()) + return; + + if (DiagID == 0) { + DiagID = S.Context.hasSameUnqualifiedType(DestType, VD->getType()) + ? diag::warn_pessimizing_move_on_return + : diag::warn_redundant_move_on_return; + } + } else { + DiagID = diag::warn_pessimizing_move_on_initialization; + const Expr *ArgStripped = Arg->IgnoreImplicit()->IgnoreParens(); + if (!ArgStripped->isRValue() || !ArgStripped->getType()->isRecordType()) + return; + } + + S.Diag(CE->getLocStart(), DiagID); + + // Get all the locations for a fix-it. Don't emit the fix-it if any location + // is within a macro. + SourceLocation CallBegin = CE->getCallee()->getLocStart(); + if (CallBegin.isMacroID()) + return; + SourceLocation RParen = CE->getRParenLoc(); + if (RParen.isMacroID()) + return; + SourceLocation LParen; + SourceLocation ArgLoc = Arg->getLocStart(); + + // Special testing for the argument location. Since the fix-it needs the + // location right before the argument, the argument location can be in a + // macro only if it is at the beginning of the macro. + while (ArgLoc.isMacroID() && + S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) { + ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).first; + } + + if (LParen.isMacroID()) + return; + + LParen = ArgLoc.getLocWithOffset(-1); + + S.Diag(CE->getLocStart(), diag::note_remove_move) + << FixItHint::CreateRemoval(SourceRange(CallBegin, LParen)) + << FixItHint::CreateRemoval(SourceRange(RParen, RParen)); +} + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -5646,6 +5887,21 @@ InitializationSequence::Perform(Sema &S, Diagnose(S, Entity, Kind, Args); return ExprError(); } + if (!ZeroInitializationFixit.empty()) { + unsigned DiagID = diag::err_default_init_const; + if (Decl *D = Entity.getDecl()) + if (S.getLangOpts().MSVCCompat && D->hasAttr<SelectAnyAttr>()) + DiagID = diag::ext_default_init_const; + + // The initialization would have succeeded with this fixit. Since the fixit + // is on the error, we need to build a valid AST in this case, so this isn't + // handled in the Failed() branch above. + QualType DestType = Entity.getType(); + S.Diag(Kind.getLocation(), DiagID) + << DestType << (bool)DestType->getAs<RecordType>() + << FixItHint::CreateInsertion(ZeroInitializationFixitLoc, + ZeroInitializationFixit); + } if (getKind() == DependentSequence) { // If the declaration is a non-dependent, incomplete array type @@ -5820,15 +6076,6 @@ InitializationSequence::Perform(Sema &S, &BasePath, IgnoreBaseAccess)) return ExprError(); - if (S.BasePathInvolvesVirtualBase(BasePath)) { - QualType T = SourceType; - if (const PointerType *Pointer = T->getAs<PointerType>()) - T = Pointer->getPointeeType(); - if (const RecordType *RecordTy = T->getAs<RecordType>()) - S.MarkVTableUsed(CurInit.get()->getLocStart(), - cast<CXXRecordDecl>(RecordTy->getDecl())); - } - ExprValueKind VK = Step->Kind == SK_CastDerivedToBaseLValue ? VK_LValue : @@ -6359,6 +6606,12 @@ InitializationSequence::Perform(Sema &S, cast<FieldDecl>(Entity.getDecl()), CurInit.get()); + // Check for std::move on construction. + if (const Expr *E = CurInit.get()) { + CheckMoveOnConstruction(S, E, + Entity.getKind() == InitializedEntity::EK_Result); + } + return CurInit; } @@ -6455,26 +6708,6 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, "Inconsistent init list check result."); } -/// Prints a fixit for adding a null initializer for |Entity|. Call this only -/// right after emitting a diagnostic. -static void maybeEmitZeroInitializationFixit(Sema &S, - InitializationSequence &Sequence, - const InitializedEntity &Entity) { - if (Entity.getKind() != InitializedEntity::EK_Variable) - return; - - VarDecl *VD = cast<VarDecl>(Entity.getDecl()); - if (VD->getInit() || VD->getLocEnd().isMacroID()) - return; - - QualType VariableTy = VD->getType().getCanonicalType(); - SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd()); - std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); - - S.Diag(Loc, diag::note_add_initializer) - << VD << FixItHint::CreateInsertion(Loc, Init); -} - bool InitializationSequence::Diagnose(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -6622,12 +6855,19 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->getSourceRange(); break; - case FK_ReferenceInitDropsQualifiers: + case FK_ReferenceInitDropsQualifiers: { + QualType SourceType = Args[0]->getType(); + QualType NonRefType = DestType.getNonReferenceType(); + Qualifiers DroppedQualifiers = + SourceType.getQualifiers() - NonRefType.getQualifiers(); + S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) - << DestType.getNonReferenceType() - << Args[0]->getType() + << SourceType + << NonRefType + << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange(); break; + } case FK_ReferenceInitFailed: S.Diag(Kind.getLocation(), diag::err_reference_bind_failed) @@ -6659,9 +6899,9 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_TooManyInitsForScalar: { SourceRange R; - if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0])) - R = SourceRange(InitList->getInit(0)->getLocEnd(), - InitList->getLocEnd()); + auto *InitList = dyn_cast<InitListExpr>(Args[0]); + if (InitList && InitList->getNumInits() == 1) + R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd()); else R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd()); @@ -6806,7 +7046,6 @@ bool InitializationSequence::Diagnose(Sema &S, } else { S.Diag(Kind.getLocation(), diag::err_default_init_const) << DestType << (bool)DestType->getAs<RecordType>(); - maybeEmitZeroInitializationFixit(S, *this, Entity); } break; @@ -7262,7 +7501,6 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity, EqualLoc, AllowExplicit); InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList); - Init.get(); ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp index 90a81f4..8220641 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp @@ -818,7 +818,6 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, NewVD->markUsed(Context); NewVD->setInit(Init); return NewVD; - } FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) { @@ -837,7 +836,8 @@ FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) { } void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, - Declarator &ParamInfo, Scope *CurScope) { + Declarator &ParamInfo, + Scope *CurScope) { // Determine if we're within a context where we know that the lambda will // be dependent, because there are template parameters in scope. bool KnownDependent = false; @@ -930,12 +930,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, PushDeclContext(CurScope, Method); // Build the lambda scope. - buildLambdaScope(LSI, Method, - Intro.Range, - Intro.Default, Intro.DefaultLoc, - ExplicitParams, - ExplicitResultType, - !Method->isConst()); + buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc, + ExplicitParams, ExplicitResultType, !Method->isConst()); // C++11 [expr.prim.lambda]p9: // A lambda-expression whose smallest enclosing scope is a block scope is a @@ -1137,7 +1133,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, bool IsInstantiation) { - LambdaScopeInfo *LSI = getCurLambda(); + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(FunctionScopes.back()); // Leave the expression-evaluation context. DiscardCleanupsInEvaluationContext(); @@ -1340,22 +1336,27 @@ static void addBlockPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { - const FunctionProtoType *Proto - = CallOperator->getType()->getAs<FunctionProtoType>(); - QualType BlockPtrTy; - { - FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); - ExtInfo.TypeQuals = 0; - QualType FunctionTy = S.Context.getFunctionType( - Proto->getReturnType(), Proto->getParamTypes(), ExtInfo); - BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); - } + const FunctionProtoType *Proto = + CallOperator->getType()->getAs<FunctionProtoType>(); + + // The function type inside the block pointer type is the same as the call + // operator with some tweaks. The calling convention is the default free + // function convention, and the type qualifications are lost. + FunctionProtoType::ExtProtoInfo BlockEPI = Proto->getExtProtoInfo(); + BlockEPI.ExtInfo = + BlockEPI.ExtInfo.withCallingConv(S.Context.getDefaultCallingConvention( + Proto->isVariadic(), /*IsCXXMethod=*/false)); + BlockEPI.TypeQuals = 0; + QualType FunctionTy = S.Context.getFunctionType( + Proto->getReturnType(), Proto->getParamTypes(), BlockEPI); + QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); + + FunctionProtoType::ExtProtoInfo ConversionEPI( + S.Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); + ConversionEPI.TypeQuals = Qualifiers::Const; + QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI); - FunctionProtoType::ExtProtoInfo ExtInfo(S.Context.getDefaultCallingConvention( - /*IsVariadic=*/false, /*IsCXXMethod=*/true)); - ExtInfo.TypeQuals = Qualifiers::Const; - QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ExtInfo); - SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name = S.Context.DeclarationNames.getCXXConversionFunctionName( @@ -1374,15 +1375,131 @@ static void addBlockPointerConversion(Sema &S, Conversion->setImplicit(true); Class->addDecl(Conversion); } + +static ExprResult performLambdaVarCaptureInitialization( + Sema &S, LambdaScopeInfo::Capture &Capture, + FieldDecl *Field, + SmallVectorImpl<VarDecl *> &ArrayIndexVars, + SmallVectorImpl<unsigned> &ArrayIndexStarts) { + assert(Capture.isVariableCapture() && "not a variable capture"); + + auto *Var = Capture.getVariable(); + SourceLocation Loc = Capture.getLocation(); + + // C++11 [expr.prim.lambda]p21: + // When the lambda-expression is evaluated, the entities that + // are captured by copy are used to direct-initialize each + // corresponding non-static data member of the resulting closure + // object. (For array members, the array elements are + // direct-initialized in increasing subscript order.) These + // initializations are performed in the (unspecified) order in + // which the non-static data members are declared. + + // C++ [expr.prim.lambda]p12: + // An entity captured by a lambda-expression is odr-used (3.2) in + // the scope containing the lambda-expression. + ExprResult RefResult = S.BuildDeclarationNameExpr( + CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var); + if (RefResult.isInvalid()) + return ExprError(); + Expr *Ref = RefResult.get(); + + QualType FieldType = Field->getType(); + + // When the variable has array type, create index variables for each + // dimension of the array. We use these index variables to subscript + // the source array, and other clients (e.g., CodeGen) will perform + // the necessary iteration with these index variables. + // + // FIXME: This is dumb. Add a proper AST representation for array + // copy-construction and use it here. + SmallVector<VarDecl *, 4> IndexVariables; + QualType BaseType = FieldType; + QualType SizeType = S.Context.getSizeType(); + ArrayIndexStarts.push_back(ArrayIndexVars.size()); + while (const ConstantArrayType *Array + = S.Context.getAsConstantArrayType(BaseType)) { + // Create the iteration variable for this array index. + IdentifierInfo *IterationVarName = nullptr; + { + SmallString<8> Str; + llvm::raw_svector_ostream OS(Str); + OS << "__i" << IndexVariables.size(); + IterationVarName = &S.Context.Idents.get(OS.str()); + } + VarDecl *IterationVar = VarDecl::Create( + S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, + S.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None); + IterationVar->setImplicit(); + IndexVariables.push_back(IterationVar); + ArrayIndexVars.push_back(IterationVar); + + // Create a reference to the iteration variable. + ExprResult IterationVarRef = + S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); + assert(!IterationVarRef.isInvalid() && + "Reference to invented variable cannot fail!"); + IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get()); + assert(!IterationVarRef.isInvalid() && + "Conversion of invented variable cannot fail!"); + + // Subscript the array with this iteration variable. + ExprResult Subscript = + S.CreateBuiltinArraySubscriptExpr(Ref, Loc, IterationVarRef.get(), Loc); + if (Subscript.isInvalid()) + return ExprError(); + + Ref = Subscript.get(); + BaseType = Array->getElementType(); + } + + // Construct the entity that we will be initializing. For an array, this + // will be first element in the array, which may require several levels + // of array-subscript entities. + SmallVector<InitializedEntity, 4> Entities; + Entities.reserve(1 + IndexVariables.size()); + Entities.push_back(InitializedEntity::InitializeLambdaCapture( + Var->getIdentifier(), FieldType, Loc)); + for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) + Entities.push_back( + InitializedEntity::InitializeElement(S.Context, 0, Entities.back())); + + InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); + InitializationSequence Init(S, Entities.back(), InitKind, Ref); + return Init.Perform(S, Entities.back(), InitKind, Ref); +} ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, - Scope *CurScope, - bool IsInstantiation) { + Scope *CurScope) { + LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back()); + ActOnFinishFunctionBody(LSI.CallOperator, Body); + return BuildLambdaExpr(StartLoc, Body->getLocEnd(), &LSI); +} + +static LambdaCaptureDefault +mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) { + switch (ICS) { + case CapturingScopeInfo::ImpCap_None: + return LCD_None; + case CapturingScopeInfo::ImpCap_LambdaByval: + return LCD_ByCopy; + case CapturingScopeInfo::ImpCap_CapturedRegion: + case CapturingScopeInfo::ImpCap_LambdaByref: + return LCD_ByRef; + case CapturingScopeInfo::ImpCap_Block: + llvm_unreachable("block capture in lambda"); + } + llvm_unreachable("Unknown implicit capture style"); +} + +ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, + LambdaScopeInfo *LSI) { // Collect information from the lambda scope. SmallVector<LambdaCapture, 4> Captures; SmallVector<Expr *, 4> CaptureInits; - LambdaCaptureDefault CaptureDefault; - SourceLocation CaptureDefaultLoc; + SourceLocation CaptureDefaultLoc = LSI->CaptureDefaultLoc; + LambdaCaptureDefault CaptureDefault = + mapImplicitCaptureStyle(LSI->ImpCaptureStyle); CXXRecordDecl *Class; CXXMethodDecl *CallOperator; SourceRange IntroducerRange; @@ -1393,7 +1510,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, SmallVector<VarDecl *, 4> ArrayIndexVars; SmallVector<unsigned, 4> ArrayIndexStarts; { - LambdaScopeInfo *LSI = getCurLambda(); CallOperator = LSI->CallOperator; Class = LSI->Lambda; IntroducerRange = LSI->IntroducerRange; @@ -1401,11 +1517,21 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, ExplicitResultType = !LSI->HasImplicitReturnType; LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; - ArrayIndexVars.swap(LSI->ArrayIndexVars); - ArrayIndexStarts.swap(LSI->ArrayIndexStarts); + CallOperator->setLexicalDeclContext(Class); + Decl *TemplateOrNonTemplateCallOperatorDecl = + CallOperator->getDescribedFunctionTemplate() + ? CallOperator->getDescribedFunctionTemplate() + : cast<Decl>(CallOperator); + + TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class); + Class->addDecl(TemplateOrNonTemplateCallOperatorDecl); + + PopExpressionEvaluationContext(); + // Translate captures. - for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { + auto CurField = Class->field_begin(); + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) { LambdaScopeInfo::Capture From = LSI->Captures[I]; assert(!From.isBlockCapture() && "Cannot capture __block variables"); bool IsImplicit = I >= LSI->NumExplicitCaptures; @@ -1417,83 +1543,33 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(), getCurrentThisType(), /*isImplicit=*/true)); + ArrayIndexStarts.push_back(ArrayIndexVars.size()); continue; } if (From.isVLATypeCapture()) { Captures.push_back( LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType)); CaptureInits.push_back(nullptr); + ArrayIndexStarts.push_back(ArrayIndexVars.size()); continue; } VarDecl *Var = From.getVariable(); - LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; + LambdaCaptureKind Kind = From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; Captures.push_back(LambdaCapture(From.getLocation(), IsImplicit, Kind, Var, From.getEllipsisLoc())); - CaptureInits.push_back(From.getInitExpr()); - } - - switch (LSI->ImpCaptureStyle) { - case CapturingScopeInfo::ImpCap_None: - CaptureDefault = LCD_None; - break; - - case CapturingScopeInfo::ImpCap_LambdaByval: - CaptureDefault = LCD_ByCopy; - break; - - case CapturingScopeInfo::ImpCap_CapturedRegion: - case CapturingScopeInfo::ImpCap_LambdaByref: - CaptureDefault = LCD_ByRef; - break; - - case CapturingScopeInfo::ImpCap_Block: - llvm_unreachable("block capture in lambda"); - break; - } - CaptureDefaultLoc = LSI->CaptureDefaultLoc; - - // C++11 [expr.prim.lambda]p4: - // If a lambda-expression does not include a - // trailing-return-type, it is as if the trailing-return-type - // denotes the following type: - // - // Skip for C++1y return type deduction semantics which uses - // different machinery. - // FIXME: Refactor and Merge the return type deduction machinery. - // FIXME: Assumes current resolution to core issue 975. - if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus14) { - deduceClosureReturnType(*LSI); - - // - if there are no return statements in the - // compound-statement, or all return statements return - // either an expression of type void or no expression or - // braced-init-list, the type void; - if (LSI->ReturnType.isNull()) { - LSI->ReturnType = Context.VoidTy; + Expr *Init = From.getInitExpr(); + if (!Init) { + auto InitResult = performLambdaVarCaptureInitialization( + *this, From, *CurField, ArrayIndexVars, ArrayIndexStarts); + if (InitResult.isInvalid()) + return ExprError(); + Init = InitResult.get(); + } else { + ArrayIndexStarts.push_back(ArrayIndexVars.size()); } - - // Create a function type with the inferred return type. - const FunctionProtoType *Proto - = CallOperator->getType()->getAs<FunctionProtoType>(); - QualType FunctionTy = Context.getFunctionType( - LSI->ReturnType, Proto->getParamTypes(), Proto->getExtProtoInfo()); - CallOperator->setType(FunctionTy); + CaptureInits.push_back(Init); } - // C++ [expr.prim.lambda]p7: - // The lambda-expression's compound-statement yields the - // function-body (8.4) of the function call operator [...]. - ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation); - CallOperator->setLexicalDeclContext(Class); - Decl *TemplateOrNonTemplateCallOperatorDecl = - CallOperator->getDescribedFunctionTemplate() - ? CallOperator->getDescribedFunctionTemplate() - : cast<Decl>(CallOperator); - - TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class); - Class->addDecl(TemplateOrNonTemplateCallOperatorDecl); - - PopExpressionEvaluationContext(); // C++11 [expr.prim.lambda]p6: // The closure type for a lambda-expression with no lambda-capture @@ -1529,7 +1605,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, - ArrayIndexStarts, Body->getLocEnd(), + ArrayIndexStarts, EndLoc, ContainsUnexpandedParameterPack); if (!CurContext->isDependentContext()) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index ad06872..c745b13 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/Lookup.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -23,7 +24,9 @@ #include "clang/AST/ExprCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Overload.h" @@ -194,10 +197,11 @@ namespace { const_iterator begin() const { return list.begin(); } const_iterator end() const { return list.end(); } - std::pair<const_iterator,const_iterator> + llvm::iterator_range<const_iterator> getNamespacesFor(DeclContext *DC) const { - return std::equal_range(begin(), end(), DC->getPrimaryContext(), - UnqualUsingEntry::Comparator()); + return llvm::make_range(std::equal_range(begin(), end(), + DC->getPrimaryContext(), + UnqualUsingEntry::Comparator())); } }; } @@ -413,6 +417,10 @@ void LookupResult::resolveKind() { if (!Unique.insert(D).second) { // If it's not unique, pull something off the back (and // continue at this index). + // FIXME: This is wrong. We need to take the more recent declaration in + // order to get the right type, default arguments, etc. We also need to + // prefer visible declarations to hidden ones (for redeclaration lookup + // in modules builds). Decls[I] = Decls[--N]; continue; } @@ -670,8 +678,8 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC); // Perform lookup into this declaration context. - DeclContext::lookup_const_result DR = DC->lookup(R.getLookupName()); - for (DeclContext::lookup_const_iterator I = DR.begin(), E = DR.end(); I != E; + DeclContext::lookup_result DR = DC->lookup(R.getLookupName()); + for (DeclContext::lookup_iterator I = DR.begin(), E = DR.end(); I != E; ++I) { NamedDecl *D = *I; if ((D = R.getAcceptableDecl(D))) { @@ -765,11 +773,8 @@ CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, // Perform direct name lookup into the namespaces nominated by the // using directives whose common ancestor is this namespace. - UnqualUsingDirectiveSet::const_iterator UI, UEnd; - std::tie(UI, UEnd) = UDirs.getNamespacesFor(NS); - - for (; UI != UEnd; ++UI) - if (LookupDirect(S, R, UI->getNominatedNamespace())) + for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(NS)) + if (LookupDirect(S, R, UUE.getNominatedNamespace())) Found = true; R.resolveKind(); @@ -1167,8 +1172,59 @@ static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); } +Module *Sema::getOwningModule(Decl *Entity) { + // If it's imported, grab its owning module. + Module *M = Entity->getImportedOwningModule(); + if (M || !isa<NamedDecl>(Entity) || !cast<NamedDecl>(Entity)->isHidden()) + return M; + assert(!Entity->isFromASTFile() && + "hidden entity from AST file has no owning module"); + + // It's local and hidden; grab or compute its owning module. + M = Entity->getLocalOwningModule(); + if (M) + return M; + + if (auto *Containing = + PP.getModuleContainingLocation(Entity->getLocation())) { + M = Containing; + } else if (Entity->isInvalidDecl() || Entity->getLocation().isInvalid()) { + // Don't bother tracking visibility for invalid declarations with broken + // locations. + cast<NamedDecl>(Entity)->setHidden(false); + } else { + // We need to assign a module to an entity that exists outside of any + // module, so that we can hide it from modules that we textually enter. + // Invent a fake module for all such entities. + if (!CachedFakeTopLevelModule) { + CachedFakeTopLevelModule = + PP.getHeaderSearchInfo().getModuleMap().findOrCreateModule( + "<top-level>", nullptr, false, false).first; + + auto &SrcMgr = PP.getSourceManager(); + SourceLocation StartLoc = + SrcMgr.getLocForStartOfFile(SrcMgr.getMainFileID()); + auto &TopLevel = + VisibleModulesStack.empty() ? VisibleModules : VisibleModulesStack[0]; + TopLevel.setVisible(CachedFakeTopLevelModule, StartLoc); + } + + M = CachedFakeTopLevelModule; + } + + if (M) + Entity->setLocalOwningModule(M); + return M; +} + +void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) { + auto *M = PP.getModuleContainingLocation(Loc); + assert(M && "hidden definition not in any module"); + Context.mergeDefinitionIntoModule(ND, M); +} + /// \brief Find the module in which the given declaration was defined. -static Module *getDefiningModule(Decl *Entity) { +static Module *getDefiningModule(Sema &S, Decl *Entity) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) { // If this function was instantiated from a template, the defining module is // the module containing the pattern. @@ -1190,15 +1246,16 @@ static Module *getDefiningModule(Decl *Entity) { // from a template. DeclContext *Context = Entity->getDeclContext(); if (Context->isFileContext()) - return Entity->getOwningModule(); - return getDefiningModule(cast<Decl>(Context)); + return S.getOwningModule(Entity); + return getDefiningModule(S, cast<Decl>(Context)); } llvm::DenseSet<Module*> &Sema::getLookupModules() { unsigned N = ActiveTemplateInstantiations.size(); for (unsigned I = ActiveTemplateInstantiationLookupModules.size(); I != N; ++I) { - Module *M = getDefiningModule(ActiveTemplateInstantiations[I].Entity); + Module *M = + getDefiningModule(*this, ActiveTemplateInstantiations[I].Entity); if (M && !LookupModulesCache.insert(M).second) M = nullptr; ActiveTemplateInstantiationLookupModules.push_back(M); @@ -1206,6 +1263,13 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() { return LookupModulesCache; } +bool Sema::hasVisibleMergedDefinition(NamedDecl *Def) { + for (Module *Merged : Context.getModulesWithMergedDefinition(Def)) + if (isModuleVisible(Merged)) + return true; + return false; +} + /// \brief Determine whether a declaration is visible to name lookup. /// /// This routine determines whether the declaration D is visible in the current @@ -1215,10 +1279,48 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() { /// path (by instantiating a template, you allow it to see the declarations that /// your module can see, including those later on in your module). bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { - assert(D->isHidden() && !SemaRef.ActiveTemplateInstantiations.empty() && - "should not call this: not in slow case"); - Module *DeclModule = D->getOwningModule(); - assert(DeclModule && "hidden decl not from a module"); + assert(D->isHidden() && "should not call this: not in slow case"); + Module *DeclModule = SemaRef.getOwningModule(D); + if (!DeclModule) { + // getOwningModule() may have decided the declaration should not be hidden. + assert(!D->isHidden() && "hidden decl not from a module"); + return true; + } + + // If the owning module is visible, and the decl is not module private, + // then the decl is visible too. (Module private is ignored within the same + // top-level module.) + if (!D->isFromASTFile() || !D->isModulePrivate()) { + if (SemaRef.isModuleVisible(DeclModule)) + return true; + // Also check merged definitions. + if (SemaRef.getLangOpts().ModulesLocalVisibility && + SemaRef.hasVisibleMergedDefinition(D)) + return true; + } + + // If this declaration is not at namespace scope nor module-private, + // then it is visible if its lexical parent has a visible definition. + DeclContext *DC = D->getLexicalDeclContext(); + if (!D->isModulePrivate() && + DC && !DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) { + // For a parameter, check whether our current template declaration's + // lexical context is visible, not whether there's some other visible + // definition of it, because parameters aren't "within" the definition. + if ((D->isTemplateParameter() || isa<ParmVarDecl>(D)) + ? isVisible(SemaRef, cast<NamedDecl>(DC)) + : SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) { + if (SemaRef.ActiveTemplateInstantiations.empty() && + // FIXME: Do something better in this case. + !SemaRef.getLangOpts().ModulesLocalVisibility) { + // Cache the fact that this declaration is implicitly visible because + // its parent has a visible definition. + D->setHidden(false); + } + return true; + } + return false; + } // Find the extra places where we need to look. llvm::DenseSet<Module*> &LookupModules = SemaRef.getLookupModules(); @@ -1243,6 +1345,10 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { return false; } +bool Sema::isVisibleSlow(const NamedDecl *D) { + return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D)); +} + /// \brief Retrieve the visible declaration corresponding to D, if any. /// /// This routine determines whether the declaration D is visible in the current @@ -1256,6 +1362,9 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { for (auto RD : D->redecls()) { if (auto ND = dyn_cast<NamedDecl>(RD)) { + // FIXME: This is wrong in the case where the previous declaration is not + // visible in the same scope as D. This needs to be done much more + // carefully. if (LookupResult::isVisible(SemaRef, ND)) return ND; } @@ -3016,17 +3125,45 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, if (Visited.visitedContext(Ctx->getPrimaryContext())) return; + // Outside C++, lookup results for the TU live on identifiers. + if (isa<TranslationUnitDecl>(Ctx) && + !Result.getSema().getLangOpts().CPlusPlus) { + auto &S = Result.getSema(); + auto &Idents = S.Context.Idents; + + // Ensure all external identifiers are in the identifier table. + if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) { + std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers()); + for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next()) + Idents.get(Name); + } + + // Walk all lookup results in the TU for each identifier. + for (const auto &Ident : Idents) { + for (auto I = S.IdResolver.begin(Ident.getValue()), + E = S.IdResolver.end(); + I != E; ++I) { + if (S.IdResolver.isDeclInScope(*I, Ctx)) { + if (NamedDecl *ND = Result.getAcceptableDecl(*I)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); + Visited.add(ND); + } + } + } + } + + return; + } + if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) Result.getSema().ForceDeclarationOfImplicitMembers(Class); // Enumerate all of the results in this context. - for (const auto &R : Ctx->lookups()) { - for (auto *I : R) { - if (NamedDecl *ND = dyn_cast<NamedDecl>(I)) { - if ((ND = Result.getAcceptableDecl(ND))) { - Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); - Visited.add(ND); - } + for (DeclContextLookupResult R : Ctx->lookups()) { + for (auto *D : R) { + if (auto *ND = Result.getAcceptableDecl(D)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); + Visited.add(ND); } } } @@ -3209,10 +3346,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, if (Entity) { // Lookup visible declarations in any namespaces found by using // directives. - UnqualUsingDirectiveSet::const_iterator UI, UEnd; - std::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity); - for (; UI != UEnd; ++UI) - LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()), + for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(Entity)) + LookupVisibleDecls(const_cast<DeclContext *>(UUE.getNominatedNamespace()), Result, /*QualifiedNameLookup=*/false, /*InBaseClass=*/false, Consumer, Visited); } @@ -3682,8 +3817,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() { TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet( ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec) - : Context(Context), CurContextChain(buildContextChain(CurContext)), - isSorted(false) { + : Context(Context), CurContextChain(buildContextChain(CurContext)) { if (NestedNameSpecifier *NNS = CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) { llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier); @@ -3702,7 +3836,6 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet( } // Add the global context as a NestedNameSpecifier - Distances.insert(1); SpecifierInfo SI = {cast<DeclContext>(Context.getTranslationUnitDecl()), NestedNameSpecifier::GlobalSpecifier(Context), 1}; DistanceMap[1].push_back(SI); @@ -3722,22 +3855,6 @@ auto TypoCorrectionConsumer::NamespaceSpecifierSet::buildContextChain( return Chain; } -void TypoCorrectionConsumer::NamespaceSpecifierSet::sortNamespaces() { - SmallVector<unsigned, 4> sortedDistances; - sortedDistances.append(Distances.begin(), Distances.end()); - - if (sortedDistances.size() > 1) - std::sort(sortedDistances.begin(), sortedDistances.end()); - - Specifiers.clear(); - for (auto D : sortedDistances) { - SpecifierInfoList &SpecList = DistanceMap[D]; - Specifiers.append(SpecList.begin(), SpecList.end()); - } - - isSorted = true; -} - unsigned TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier( DeclContextList &DeclChain, NestedNameSpecifier *&NNS) { @@ -3818,8 +3935,6 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier( llvm::makeArrayRef(NewNameSpecifierIdentifiers)); } - isSorted = false; - Distances.insert(NumSpecifiers); SpecifierInfo SI = {Ctx, NNS, NumSpecifiers}; DistanceMap[NumSpecifiers].push_back(SI); } @@ -4294,7 +4409,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Record the failure's location if needed and return an empty correction. If // this was an unqualified lookup and we believe the callback object did not // filter out possible corrections, also cache the failure for the typo. - return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC); } /// \brief Try to "correct" a typo in the source code by finding @@ -4347,9 +4462,7 @@ TypoExpr *Sema::CorrectTypoDelayed( TypoCorrection Empty; auto Consumer = makeTypoCorrectionConsumer( TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, - EnteringContext, OPT, - /*SearchModules=*/(Mode == CTK_ErrorRecovery) && getLangOpts().Modules && - getLangOpts().ModulesSearchAll); + EnteringContext, OPT, Mode == CTK_ErrorRecovery); if (!Consumer || Consumer->empty()) return nullptr; @@ -4491,18 +4604,18 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, /// Find which declaration we should import to provide the definition of /// the given declaration. -static const NamedDecl *getDefinitionToImport(const NamedDecl *D) { - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) +static NamedDecl *getDefinitionToImport(NamedDecl *D) { + if (VarDecl *VD = dyn_cast<VarDecl>(D)) return VD->getDefinition(); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - return FD->isDefined(FD) ? FD : nullptr; - if (const TagDecl *TD = dyn_cast<TagDecl>(D)) + return FD->isDefined(FD) ? const_cast<FunctionDecl*>(FD) : nullptr; + if (TagDecl *TD = dyn_cast<TagDecl>(D)) return TD->getDefinition(); - if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) return ID->getDefinition(); - if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) + if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) return PD->getDefinition(); - if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) + if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) return getDefinitionToImport(TD->getTemplatedDecl()); return nullptr; } @@ -4535,10 +4648,10 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, // Suggest importing a module providing the definition of this entity, if // possible. - const NamedDecl *Def = getDefinitionToImport(Decl); + NamedDecl *Def = getDefinitionToImport(Decl); if (!Def) Def = Decl; - Module *Owner = Def->getOwningModule(); + Module *Owner = getOwningModule(Def); assert(Owner && "definition of hidden declaration is not in a module"); Diag(Correction.getCorrectionRange().getBegin(), diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp index 72b6020..5e7b4b8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -19,6 +19,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallString.h" @@ -406,9 +407,11 @@ Sema::HandlePropertyInClassExtension(Scope *S, // this conversion is safe only because the wider type is for a 'readonly' // property in primary class and 'narrowed' type for a 'readwrite' property // in continuation class. - if (!isa<ObjCObjectPointerType>(PIDecl->getType()) || - !isa<ObjCObjectPointerType>(PDecl->getType()) || - (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(), + QualType PrimaryClassPropertyT = Context.getCanonicalType(PIDecl->getType()); + QualType ClassExtPropertyT = Context.getCanonicalType(PDecl->getType()); + if (!isa<ObjCObjectPointerType>(PrimaryClassPropertyT) || + !isa<ObjCObjectPointerType>(ClassExtPropertyT) || + (!isObjCPointerConversion(ClassExtPropertyT, PrimaryClassPropertyT, ConvertedType, IncompatibleObjC)) || IncompatibleObjC) { Diag(AtLoc, @@ -1854,6 +1857,39 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule); else Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule); + + // Look for a getter explicitly declared alongside the property. + // If we find one, use its location for the note. + SourceLocation noteLoc = PD->getLocation(); + SourceLocation fixItLoc; + for (auto *getterRedecl : method->redecls()) { + if (getterRedecl->isImplicit()) + continue; + if (getterRedecl->getDeclContext() != PD->getDeclContext()) + continue; + noteLoc = getterRedecl->getLocation(); + fixItLoc = getterRedecl->getLocEnd(); + } + + Preprocessor &PP = getPreprocessor(); + TokenValue tokens[] = { + tok::kw___attribute, tok::l_paren, tok::l_paren, + PP.getIdentifierInfo("objc_method_family"), tok::l_paren, + PP.getIdentifierInfo("none"), tok::r_paren, + tok::r_paren, tok::r_paren + }; + StringRef spelling = "__attribute__((objc_method_family(none)))"; + StringRef macroName = PP.getLastMacroWithSpelling(noteLoc, tokens); + if (!macroName.empty()) + spelling = macroName; + + auto noteDiag = Diag(noteLoc, diag::note_cocoa_naming_declare_family) + << method->getDeclName() << spelling; + if (fixItLoc.isValid()) { + SmallString<64> fixItText(" "); + fixItText += spelling; + noteDiag << FixItHint::CreateInsertion(fixItLoc, fixItText); + } } } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp index d72942a..cfe8db3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp @@ -82,10 +82,12 @@ private: }; typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy; typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy; + typedef llvm::DenseSet<VarDecl *> LoopControlVariablesSetTy; struct SharingMapTy { DeclSAMapTy SharingMap; AlignedMapTy AlignedMap; + LoopControlVariablesSetTy LCVSet; DefaultDataSharingAttributes DefaultAttr; SourceLocation DefaultAttrLoc; OpenMPDirectiveKind Directive; @@ -93,22 +95,28 @@ private: Scope *CurScope; SourceLocation ConstructLoc; bool OrderedRegion; + unsigned CollapseNumber; SourceLocation InnerTeamsRegionLoc; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) - : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified), + : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified), Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope), - ConstructLoc(Loc), OrderedRegion(false), InnerTeamsRegionLoc() {} + ConstructLoc(Loc), OrderedRegion(false), CollapseNumber(1), + InnerTeamsRegionLoc() {} SharingMapTy() - : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified), + : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified), Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr), - ConstructLoc(), OrderedRegion(false), InnerTeamsRegionLoc() {} + ConstructLoc(), OrderedRegion(false), CollapseNumber(1), + InnerTeamsRegionLoc() {} }; typedef SmallVector<SharingMapTy, 64> StackTy; /// \brief Stack of used declaration and their data-sharing attributes. StackTy Stack; + /// \brief true, if check for DSA must be from parent directive, false, if + /// from current directive. + bool FromParent; Sema &SemaRef; typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator; @@ -119,7 +127,10 @@ private: bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter); public: - explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {} + explicit DSAStackTy(Sema &S) : Stack(1), FromParent(false), SemaRef(S) {} + + bool isFromParent() const { return FromParent; } + void setFromParent(bool Flag) { FromParent = Flag; } void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc) { @@ -137,6 +148,12 @@ public: /// for diagnostics. DeclRefExpr *addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE); + /// \brief Register specified variable as loop control variable. + void addLoopControlVariable(VarDecl *D); + /// \brief Check if the specified variable is a loop control variable for + /// current region. + bool isLoopControlVariable(VarDecl *D); + /// \brief Adds explicit data sharing attribute to the specified declaration. void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A); @@ -209,6 +226,13 @@ public: return false; } + /// \brief Set collapse value for the region. + void setCollapseNumber(unsigned Val) { Stack.back().CollapseNumber = Val; } + /// \brief Return collapse value for region. + unsigned getCollapseNumber() const { + return Stack.back().CollapseNumber; + } + /// \brief Marks current target region as one with closely nested teams /// region. void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) { @@ -238,6 +262,7 @@ bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) { DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, VarDecl *D) { + D = D->getCanonicalDecl(); DSAVarData DVar; if (Iter == std::prev(Stack.rend())) { // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced @@ -308,8 +333,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, // bound to the current team is shared. if (DVar.DKind == OMPD_task) { DSAVarData DVarTemp; - for (StackTy::reverse_iterator I = std::next(Iter), - EE = std::prev(Stack.rend()); + for (StackTy::reverse_iterator I = std::next(Iter), EE = Stack.rend(); I != EE; ++I) { // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables // Referenced @@ -343,6 +367,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) { assert(Stack.size() > 1 && "Data sharing attributes stack is empty"); + D = D->getCanonicalDecl(); auto It = Stack.back().AlignedMap.find(D); if (It == Stack.back().AlignedMap.end()) { assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); @@ -355,7 +380,20 @@ DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) { return nullptr; } +void DSAStackTy::addLoopControlVariable(VarDecl *D) { + assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); + D = D->getCanonicalDecl(); + Stack.back().LCVSet.insert(D); +} + +bool DSAStackTy::isLoopControlVariable(VarDecl *D) { + assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); + D = D->getCanonicalDecl(); + return Stack.back().LCVSet.count(D) > 0; +} + void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) { + D = D->getCanonicalDecl(); if (A == OMPC_threadprivate) { Stack[0].SharingMap[D].Attributes = A; Stack[0].SharingMap[D].RefExpr = E; @@ -367,6 +405,7 @@ void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) { } bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) { + D = D->getCanonicalDecl(); if (Stack.size() > 2) { reverse_iterator I = Iter, E = std::prev(Stack.rend()); Scope *TopScope = nullptr; @@ -385,16 +424,41 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) { return false; } +/// \brief Build a variable declaration for OpenMP loop iteration variable. +static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, + StringRef 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_None); + Decl->setImplicit(); + return Decl; +} + +static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, + SourceLocation Loc, + bool RefersToCapture = false) { + D->setReferenced(); + D->markUsed(S.Context); + return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(), + SourceLocation(), D, RefersToCapture, Loc, Ty, + VK_LValue); +} + DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { + D = D->getCanonicalDecl(); DSAVarData DVar; // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct, C/C++, predetermined, p.1] // Variables appearing in threadprivate directives are threadprivate. if (D->getTLSKind() != VarDecl::TLS_None || - D->getStorageClass() == SC_Register) { - DVar.CKind = OMPC_threadprivate; - return DVar; + (D->getStorageClass() == SC_Register && D->hasAttr<AsmLabelAttr>() && + !D->isLocalVarDecl())) { + addDSA(D, buildDeclRefExpr(SemaRef, D, D->getType().getNonReferenceType(), + D->getLocation()), + OMPC_threadprivate); } if (Stack[0].SharingMap.count(D)) { DVar.RefExpr = Stack[0].SharingMap[D].RefExpr; @@ -421,29 +485,28 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { DVar.CKind = OMPC_private; return DVar; } - } - // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced - // in a Construct, C/C++, predetermined, p.4] - // Static data members are shared. - if (D->isStaticDataMember()) { - // Variables with const-qualified type having no mutable member may be - // listed in a firstprivate clause, even if they are static data members. - DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate), - MatchesAlways(), FromParent); - if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr) - return DVar; + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, predetermined, p.4] + // Static data members are shared. + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, C/C++, predetermined, p.7] + // Variables with static storage duration that are declared in a scope + // inside the construct are shared. + if (D->isStaticDataMember() || D->isStaticLocal()) { + DSAVarData DVarTemp = + hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent); + if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) + return DVar; - DVar.CKind = OMPC_shared; - return DVar; + DVar.CKind = OMPC_shared; + return DVar; + } } QualType Type = D->getType().getNonReferenceType().getCanonicalType(); bool IsConstant = Type.isConstant(SemaRef.getASTContext()); - while (Type->isArrayType()) { - QualType ElemType = cast<ArrayType>(Type.getTypePtr())->getElementType(); - Type = ElemType.getNonReferenceType().getCanonicalType(); - } + Type = SemaRef.getASTContext().getBaseElementType(Type); // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct, C/C++, predetermined, p.6] // Variables with const qualified type having no mutable member are @@ -463,15 +526,6 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { return DVar; } - // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced - // in a Construct, C/C++, predetermined, p.7] - // Variables with static storage duration that are declared in a scope - // inside the construct are shared. - if (D->isStaticLocal()) { - DVar.CKind = OMPC_shared; - return DVar; - } - // Explicitly specified attributes and local variables with predetermined // attributes. auto I = std::prev(StartI); @@ -485,6 +539,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { } DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) { + D = D->getCanonicalDecl(); auto StartI = Stack.rbegin(); auto EndI = std::prev(Stack.rend()); if (FromParent && StartI != EndI) { @@ -497,6 +552,7 @@ template <class ClausesPredicate, class DirectivesPredicate> DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred, DirectivesPredicate DPred, bool FromParent) { + D = D->getCanonicalDecl(); auto StartI = std::next(Stack.rbegin()); auto EndI = std::prev(Stack.rend()); if (FromParent && StartI != EndI) { @@ -516,6 +572,7 @@ template <class ClausesPredicate, class DirectivesPredicate> DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred, DirectivesPredicate DPred, bool FromParent) { + D = D->getCanonicalDecl(); auto StartI = std::next(Stack.rbegin()); auto EndI = std::prev(Stack.rend()); if (FromParent && StartI != EndI) { @@ -554,12 +611,17 @@ void Sema::InitDataSharingAttributesStack() { bool Sema::IsOpenMPCapturedVar(VarDecl *VD) { assert(LangOpts.OpenMP && "OpenMP is not allowed"); + VD = VD->getCanonicalDecl(); if (DSAStack->getCurrentDirective() != OMPD_unknown) { - auto DVarPrivate = DSAStack->getTopDSA(VD, /*FromParent=*/false); + if (DSAStack->isLoopControlVariable(VD) || + (VD->hasLocalStorage() && + isParallelOrTaskRegion(DSAStack->getCurrentDirective()))) + return true; + auto DVarPrivate = DSAStack->getTopDSA(VD, DSAStack->isFromParent()); if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind)) return true; DVarPrivate = DSAStack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), - /*FromParent=*/false); + DSAStack->isFromParent()); return DVarPrivate.CKind != OMPC_unknown; } return false; @@ -574,6 +636,14 @@ void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, PushExpressionEvaluationContext(PotentiallyEvaluated); } +void Sema::StartOpenMPClauses() { + DSAStack->setFromParent(/*Flag=*/true); +} + +void Sema::EndOpenMPClauses() { + DSAStack->setFromParent(/*Flag=*/false); +} + void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { // OpenMP [2.14.3.5, Restrictions, C/C++, p.1] // A variable of class type (or array thereof) that appears in a lastprivate @@ -581,46 +651,41 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { // class type, unless the list item is also specified in a firstprivate // clause. if (auto D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) { - for (auto C : D->clauses()) { - if (auto Clause = dyn_cast<OMPLastprivateClause>(C)) { - for (auto VarRef : Clause->varlists()) { - if (VarRef->isValueDependent() || VarRef->isTypeDependent()) + for (auto *C : D->clauses()) { + if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) { + SmallVector<Expr *, 8> PrivateCopies; + for (auto *DE : Clause->varlists()) { + if (DE->isValueDependent() || DE->isTypeDependent()) { + PrivateCopies.push_back(nullptr); continue; - auto VD = cast<VarDecl>(cast<DeclRefExpr>(VarRef)->getDecl()); + } + auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl()); + QualType Type = VD->getType(); auto DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind == OMPC_lastprivate) { - SourceLocation ELoc = VarRef->getExprLoc(); - auto Type = VarRef->getType(); - if (Type->isArrayType()) - Type = QualType(Type->getArrayElementTypeNoTypeQual(), 0); - CXXRecordDecl *RD = - getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; - // FIXME This code must be replaced by actual constructing of the - // lastprivate variable. - if (RD) { - CXXConstructorDecl *CD = LookupDefaultConstructor(RD); - PartialDiagnostic PD = - PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); - if (!CD || - CheckConstructorAccess( - ELoc, CD, InitializedEntity::InitializeTemporary(Type), - CD->getAccess(), PD) == AR_inaccessible || - CD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_lastprivate) << 0; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl - : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; - } - MarkFunctionReferenced(ELoc, CD); - DiagnoseUseOfDecl(CD, ELoc); - } + // Generate helper private variable and initialize it with the + // default value. The address of the original variable is replaced + // by the address of the new private variable in CodeGen. This new + // variable is not added to IdResolver, so the code in the OpenMP + // region uses original variable for proper diagnostics. + auto *VDPrivate = + buildVarDecl(*this, DE->getExprLoc(), Type.getUnqualifiedType(), + VD->getName()); + ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); + if (VDPrivate->isInvalidDecl()) + continue; + PrivateCopies.push_back(buildDeclRefExpr( + *this, VDPrivate, DE->getType(), DE->getExprLoc())); + } else { + // The variable is also a firstprivate, so initialization sequence + // for private copy is generated already. + PrivateCopies.push_back(nullptr); } } + // Set initializers to private copies if no errors were found. + if (PrivateCopies.size() == Clause->varlist_size()) { + Clause->setPrivateCopies(PrivateCopies); + } } } } @@ -630,6 +695,10 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { PopExpressionEvaluationContext(); } +static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, + Expr *NumIterations, Sema &SemaRef, + Scope *S); + namespace { class VarDeclFilterCCC : public CorrectionCandidateCallback { @@ -763,14 +832,14 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, // OpenMP [2.9.2, Restrictions, C/C++, p.2-6] // A threadprivate directive must lexically precede all references to any // of the variables in its list. - if (VD->isUsed()) { + if (VD->isUsed() && !DSAStack->isThreadPrivate(VD)) { Diag(Id.getLoc(), diag::err_omp_var_used) << getOpenMPDirectiveName(OMPD_threadprivate) << VD; return ExprError(); } QualType ExprType = VD->getType().getNonReferenceType(); - ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_LValue, Id.getLoc()); + ExprResult DE = buildDeclRefExpr(*this, VD, ExprType, Id.getLoc()); return DE; } @@ -821,6 +890,13 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) { VarDecl *VD = cast<VarDecl>(DE->getDecl()); SourceLocation ILoc = DE->getExprLoc(); + QualType QType = VD->getType(); + if (QType->isDependentType() || QType->isInstantiationDependentType()) { + // It will be analyzed later. + Vars.push_back(DE); + continue; + } + // OpenMP [2.9.2, Restrictions, C/C++, p.10] // A threadprivate variable must not have an incomplete type. if (RequireCompleteType(ILoc, VD->getType(), @@ -843,7 +919,8 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) { // Check if this is a TLS variable. if (VD->getTLSKind() != VarDecl::TLS_None || - VD->getStorageClass() == SC_Register) { + (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() && + !VD->isLocalVarDecl())) { Diag(ILoc, diag::err_omp_var_thread_local) << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1); bool IsDecl = @@ -1121,7 +1198,11 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { break; } case OMPD_parallel_sections: { + QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); + QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); Sema::CapturedParamNameType Params[] = { + std::make_pair(".global_tid.", KmpInt32PtrTy), + std::make_pair(".bound_tid.", KmpInt32PtrTy), std::make_pair(StringRef(), QualType()) // __context with shared vars }; ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, @@ -1129,11 +1210,28 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { break; } case OMPD_task: { + QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); + QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()}; + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = true; + QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI); Sema::CapturedParamNameType Params[] = { + std::make_pair(".global_tid.", KmpInt32Ty), + std::make_pair(".part_id.", KmpInt32Ty), + std::make_pair(".privates.", + Context.VoidPtrTy.withConst().withRestrict()), + std::make_pair( + ".copy_fn.", + Context.getPointerType(CopyFnType).withConst().withRestrict()), std::make_pair(StringRef(), QualType()) // __context with shared vars }; ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, Params); + // Mark this captured region as inlined, because we don't use outlined + // function directly. + getCurCapturedRegion()->TheCapturedDecl->addAttr( + AlwaysInlineAttr::CreateImplicit( + Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange())); break; } case OMPD_ordered: { @@ -1183,6 +1281,36 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { } } +StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, + ArrayRef<OMPClause *> Clauses) { + if (!S.isUsable()) { + ActOnCapturedRegionError(); + return StmtError(); + } + // This is required for proper codegen. + for (auto *Clause : Clauses) { + if (isOpenMPPrivate(Clause->getClauseKind()) || + Clause->getClauseKind() == OMPC_copyprivate) { + // Mark all variables in private list clauses as used in inner region. + for (auto *VarRef : Clause->children()) { + if (auto *E = cast_or_null<Expr>(VarRef)) { + MarkDeclarationsReferencedInExpr(E); + } + } + } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective()) && + Clause->getClauseKind() == OMPC_schedule) { + // Mark all variables in private list clauses as used in inner region. + // Required for proper codegen of combined directives. + // TODO: add processing for other clauses. + if (auto *E = cast_or_null<Expr>( + cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) { + MarkDeclarationsReferencedInExpr(E); + } + } + } + return ActOnCapturedRegionEnd(S.get()); +} + static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, @@ -1914,7 +2042,7 @@ public: TestIsStrictOp(false), SubtractStep(false) {} /// \brief Check init-expr for canonical loop form and save loop counter /// variable - #Var and its initialization value - #LB. - bool CheckInit(Stmt *S); + bool CheckInit(Stmt *S, bool EmitDiags = true); /// \brief Check test-expr for canonical form, save upper-bound (#UB), flags /// for less/greater and for strict/non-strict comparison. bool CheckCond(Expr *S); @@ -1935,6 +2063,8 @@ public: bool ShouldSubtractStep() const { return SubtractStep; } /// \brief Build the expression to calculate the number of iterations. Expr *BuildNumIterations(Scope *S, const bool LimitedType) const; + /// \brief Build the precondition expression for the loops. + Expr *BuildPreCond(Scope *S, Expr *Cond) const; /// \brief Build reference expression to the counter be used for codegen. Expr *BuildCounterVar() const; /// \brief Build initization of the counter be used for codegen. @@ -2052,7 +2182,7 @@ bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) { return false; } -bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) { +bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) { // Check init-expr for canonical loop form and save loop counter // variable - #Var and its initialization value - #LB. // OpenMP [2.6] Canonical loop form. init-expr may be one of the following: @@ -2062,7 +2192,9 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) { // pointer-type var = lb // if (!S) { - SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init); + if (EmitDiags) { + SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init); + } return true; } InitSrcRange = S->getSourceRange(); @@ -2078,7 +2210,7 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) { if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) { if (Var->hasInit()) { // Accept non-canonical init form here but emit ext. warning. - if (Var->getInitStyle() != VarDecl::CInit) + if (Var->getInitStyle() != VarDecl::CInit && EmitDiags) SemaRef.Diag(S->getLocStart(), diag::ext_omp_loop_not_canonical_init) << S->getSourceRange(); @@ -2092,8 +2224,10 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S) { return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), DRE, CE->getArg(1)); - SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init) - << S->getSourceRange(); + if (EmitDiags) { + SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init) + << S->getSourceRange(); + } return true; } @@ -2338,11 +2472,22 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S, return Diff.get(); } +Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const { + // Try to build LB <op> UB, where <op> is <, >, <=, or >=. + bool Suppress = SemaRef.getDiagnostics().getSuppressAllDiagnostics(); + SemaRef.getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true); + auto CondExpr = SemaRef.BuildBinOp( + S, DefaultLoc, TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE) + : (TestIsStrictOp ? BO_GT : BO_GE), + LB, UB); + SemaRef.getDiagnostics().setSuppressAllDiagnostics(Suppress); + // Otherwise use original loop conditon and evaluate it in runtime. + return CondExpr.isUsable() ? CondExpr.get() : Cond; +} + /// \brief Build reference expression to the counter be used for codegen. Expr *OpenMPIterationSpaceChecker::BuildCounterVar() const { - return DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), - GetIncrementSrcRange().getBegin(), Var, false, - DefaultLoc, Var->getType(), VK_LValue); + return buildDeclRefExpr(SemaRef, Var, Var->getType(), DefaultLoc); } /// \brief Build initization of the counter be used for codegen. @@ -2353,6 +2498,8 @@ Expr *OpenMPIterationSpaceChecker::BuildCounterStep() const { return Step; } /// \brief Iteration space of a single for loop. struct LoopIterationSpace { + /// \brief Condition of the loop. + Expr *PreCond; /// \brief This expression calculates the number of iterations in the loop. /// It is always possible to calculate it before starting the loop. Expr *NumIterations; @@ -2375,6 +2522,20 @@ struct LoopIterationSpace { } // namespace +void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { + assert(getLangOpts().OpenMP && "OpenMP is not active."); + assert(Init && "Expected loop in canonical form."); + unsigned CollapseIteration = DSAStack->getCollapseNumber(); + if (CollapseIteration > 0 && + isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { + OpenMPIterationSpaceChecker ISC(*this, ForLoc); + if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) { + DSAStack->addLoopControlVariable(ISC.GetLoopVar()); + } + DSAStack->setCollapseNumber(CollapseIteration - 1); + } +} + /// \brief Called on a for stmt to check and extract its iteration space /// for further processing (such as collapsing). static bool CheckOpenMPIterationSpace( @@ -2453,32 +2614,27 @@ static bool CheckOpenMPIterationSpace( ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate) : OMPC_private; if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && - DVar.CKind != PredeterminedCKind) || + DVar.CKind != OMPC_threadprivate && DVar.CKind != PredeterminedCKind) || (isOpenMPWorksharingDirective(DKind) && !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private && - DVar.CKind != OMPC_lastprivate)) && - (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { + DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_threadprivate)) && + ((DVar.CKind != OMPC_private && DVar.CKind != OMPC_threadprivate) || + DVar.RefExpr != nullptr)) { SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(PredeterminedCKind); - ReportOriginalDSA(SemaRef, &DSA, Var, DVar, true); + if (DVar.RefExpr == nullptr) + DVar.CKind = PredeterminedCKind; + ReportOriginalDSA(SemaRef, &DSA, Var, DVar, /*IsLoopIterVar=*/true); HasErrors = true; } else if (LoopVarRefExpr != nullptr) { // Make the loop iteration variable private (for worksharing constructs), // linear (for simd directives with the only one associated loop) or // lastprivate (for simd directives with several collapsed loops). - // FIXME: the next check and error message must be removed once the - // capturing of global variables in loops is fixed. if (DVar.CKind == OMPC_unknown) DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(), /*FromParent=*/false); - if (!Var->hasLocalStorage() && DVar.CKind == OMPC_unknown) { - SemaRef.Diag(Init->getLocStart(), diag::err_omp_global_loop_var_dsa) - << getOpenMPClauseName(PredeterminedCKind) - << getOpenMPDirectiveName(DKind); - HasErrors = true; - } else - DSA.addDSA(Var, LoopVarRefExpr, PredeterminedCKind); + DSA.addDSA(Var, LoopVarRefExpr, PredeterminedCKind); } assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars"); @@ -2493,6 +2649,7 @@ static bool CheckOpenMPIterationSpace( return HasErrors; // Build the loop's iteration space representation. + ResultIterSpace.PreCond = ISC.BuildPreCond(DSA.getCurScope(), For->getCond()); ResultIterSpace.NumIterations = ISC.BuildNumIterations( DSA.getCurScope(), /* LimitedType */ isOpenMPWorksharingDirective(DKind)); ResultIterSpace.CounterVar = ISC.BuildCounterVar(); @@ -2503,7 +2660,8 @@ static bool CheckOpenMPIterationSpace( ResultIterSpace.IncSrcRange = ISC.GetIncrementSrcRange(); ResultIterSpace.Subtract = ISC.ShouldSubtractStep(); - HasErrors |= (ResultIterSpace.NumIterations == nullptr || + HasErrors |= (ResultIterSpace.PreCond == nullptr || + ResultIterSpace.NumIterations == nullptr || ResultIterSpace.CounterVar == nullptr || ResultIterSpace.CounterInit == nullptr || ResultIterSpace.CounterStep == nullptr); @@ -2511,18 +2669,6 @@ static bool CheckOpenMPIterationSpace( return HasErrors; } -/// \brief Build a variable declaration for OpenMP loop iteration variable. -static VarDecl *BuildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, - StringRef 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_None); - Decl->setImplicit(); - return Decl; -} - /// \brief Build 'VarRef = Start + Iter * Step'. static ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, @@ -2648,6 +2794,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are // the iteration counts of the collapsed for loops. + // Precondition tests if there is at least one iteration (all conditions are + // true). + auto PreCond = ExprResult(IterSpaces[0].PreCond); auto N0 = IterSpaces[0].NumIterations; ExprResult LastIteration32 = WidenIterationCount(32 /* Bits */, N0, SemaRef); ExprResult LastIteration64 = WidenIterationCount(64 /* Bits */, N0, SemaRef); @@ -2660,6 +2809,10 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, Scope *CurScope = DSA.getCurScope(); for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) { + if (PreCond.isUsable()) { + PreCond = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LAnd, + PreCond.get(), IterSpaces[Cnt].PreCond); + } auto N = IterSpaces[Cnt].NumIterations; AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32; if (LastIteration32.isUsable()) @@ -2703,10 +2856,10 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, if (!IsConstant) { SourceLocation SaveLoc; VarDecl *SaveVar = - BuildVarDecl(SemaRef, SaveLoc, LastIteration.get()->getType(), + buildVarDecl(SemaRef, SaveLoc, LastIteration.get()->getType(), ".omp.last.iteration"); - ExprResult SaveRef = SemaRef.BuildDeclRefExpr( - SaveVar, LastIteration.get()->getType(), VK_LValue, SaveLoc); + ExprResult SaveRef = buildDeclRefExpr( + SemaRef, SaveVar, LastIteration.get()->getType(), SaveLoc); CalcLastIteration = SemaRef.BuildBinOp(CurScope, SaveLoc, BO_Assign, SaveRef.get(), LastIteration.get()); LastIteration = SaveRef; @@ -2721,25 +2874,20 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin(); - // Precondition tests if there is at least one iteration (LastIteration > 0). - ExprResult PreCond = SemaRef.BuildBinOp( - CurScope, InitLoc, BO_GT, LastIteration.get(), - SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get()); - QualType VType = LastIteration.get()->getType(); // Build variables passed into runtime, nesessary for worksharing directives. ExprResult LB, UB, IL, ST, EUB; if (isOpenMPWorksharingDirective(DKind)) { // Lower bound variable, initialized with zero. - VarDecl *LBDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.lb"); - LB = SemaRef.BuildDeclRefExpr(LBDecl, VType, VK_LValue, InitLoc); + VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb"); + LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc); SemaRef.AddInitializerToDecl( LBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), /*DirectInit*/ false, /*TypeMayContainAuto*/ false); // Upper bound variable, initialized with last iteration number. - VarDecl *UBDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.ub"); - UB = SemaRef.BuildDeclRefExpr(UBDecl, VType, VK_LValue, InitLoc); + VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub"); + UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc); SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(), /*DirectInit*/ false, /*TypeMayContainAuto*/ false); @@ -2747,15 +2895,15 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // A 32-bit variable-flag where runtime returns 1 for the last iteration. // This will be used to implement clause 'lastprivate'. QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true); - VarDecl *ILDecl = BuildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last"); - IL = SemaRef.BuildDeclRefExpr(ILDecl, Int32Ty, VK_LValue, InitLoc); + VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last"); + IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc); SemaRef.AddInitializerToDecl( ILDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), /*DirectInit*/ false, /*TypeMayContainAuto*/ false); // Stride variable returned by runtime (we initialize it to 1 by default). - VarDecl *STDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.stride"); - ST = SemaRef.BuildDeclRefExpr(STDecl, VType, VK_LValue, InitLoc); + VarDecl *STDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.stride"); + ST = buildDeclRefExpr(SemaRef, STDecl, VType, InitLoc); SemaRef.AddInitializerToDecl( STDecl, SemaRef.ActOnIntegerConstant(InitLoc, 1).get(), /*DirectInit*/ false, /*TypeMayContainAuto*/ false); @@ -2775,8 +2923,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, ExprResult IV; ExprResult Init; { - VarDecl *IVDecl = BuildVarDecl(SemaRef, InitLoc, VType, ".omp.iv"); - IV = SemaRef.BuildDeclRefExpr(IVDecl, VType, VK_LValue, InitLoc); + VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.iv"); + IV = buildDeclRefExpr(SemaRef, IVDecl, VType, InitLoc); Expr *RHS = isOpenMPWorksharingDirective(DKind) ? LB.get() : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); @@ -2864,9 +3012,13 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, break; } - // Build update: IS.CounterVar = IS.Start + Iter * IS.Step + // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step + auto *CounterVar = buildDeclRefExpr( + SemaRef, cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl()), + IS.CounterVar->getType(), IS.CounterVar->getExprLoc(), + /*RefersToCapture=*/true); ExprResult Update = - BuildCounterUpdate(SemaRef, CurScope, UpdLoc, IS.CounterVar, + BuildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter, IS.CounterStep, IS.Subtract); if (!Update.isUsable()) { HasErrors = true; @@ -2875,7 +3027,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step ExprResult Final = BuildCounterUpdate( - SemaRef, CurScope, UpdLoc, IS.CounterVar, IS.CounterInit, + SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, IS.NumIterations, IS.CounterStep, IS.Subtract); if (!Final.isUsable()) { HasErrors = true; @@ -2915,6 +3067,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // Save results Built.IterationVarRef = IV.get(); Built.LastIteration = LastIteration.get(); + Built.NumIterations = NumIterations.get(); Built.CalcLastIteration = CalcLastIteration.get(); Built.PreCond = PreCond.get(); Built.Cond = Cond.get(); @@ -2933,11 +3086,11 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, } static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { - auto CollapseFilter = [](const OMPClause *C) -> bool { + auto &&CollapseFilter = [](const OMPClause *C) -> bool { return C->getClauseKind() == OMPC_collapse; }; OMPExecutableDirective::filtered_clause_iterator<decltype(CollapseFilter)> I( - Clauses, CollapseFilter); + Clauses, std::move(CollapseFilter)); if (I) return cast<OMPCollapseClause>(*I)->getNumForLoops(); return nullptr; @@ -2958,6 +3111,16 @@ StmtResult Sema::ActOnOpenMPSimdDirective( assert((CurContext->isDependentContext() || B.builtAll()) && "omp simd loop exprs were not built"); + if (!CurContext->isDependentContext()) { + // Finalize the clauses that need pre-built expressions for CodeGen. + for (auto C : Clauses) { + if (auto LC = dyn_cast<OMPLinearClause>(C)) + if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), + B.NumIterations, *this, CurScope)) + return StmtError(); + } + } + getCurFunction()->setHasBranchProtectedScope(); return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); @@ -3055,6 +3218,23 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); + // OpenMP [2.7.3, single Construct, Restrictions] + // The copyprivate clause must not be used with the nowait clause. + OMPClause *Nowait = nullptr; + OMPClause *Copyprivate = nullptr; + for (auto *Clause : Clauses) { + if (Clause->getClauseKind() == OMPC_nowait) + Nowait = Clause; + else if (Clause->getClauseKind() == OMPC_copyprivate) + Copyprivate = Clause; + if (Copyprivate && Nowait) { + Diag(Copyprivate->getLocStart(), + diag::err_omp_single_copyprivate_with_nowait); + Diag(Nowait->getLocStart(), diag::note_omp_nowait_clause_here); + return StmtError(); + } + } + return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); } @@ -3219,6 +3399,246 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt, return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt); } +namespace { +/// \brief Helper class for checking expression in 'omp atomic [update]' +/// construct. +class OpenMPAtomicUpdateChecker { + /// \brief Error results for atomic update expressions. + enum ExprAnalysisErrorCode { + /// \brief A statement is not an expression statement. + NotAnExpression, + /// \brief Expression is not builtin binary or unary operation. + NotABinaryOrUnaryExpression, + /// \brief Unary operation is not post-/pre- increment/decrement operation. + NotAnUnaryIncDecExpression, + /// \brief An expression is not of scalar type. + NotAScalarType, + /// \brief A binary operation is not an assignment operation. + NotAnAssignmentOp, + /// \brief RHS part of the binary operation is not a binary expression. + NotABinaryExpression, + /// \brief RHS part is not additive/multiplicative/shift/biwise binary + /// expression. + NotABinaryOperator, + /// \brief RHS binary operation does not have reference to the updated LHS + /// part. + NotAnUpdateExpression, + /// \brief No errors is found. + NoError + }; + /// \brief Reference to Sema. + Sema &SemaRef; + /// \brief A location for note diagnostics (when error is found). + SourceLocation NoteLoc; + /// \brief 'x' lvalue part of the source atomic expression. + Expr *X; + /// \brief 'expr' rvalue part of the source atomic expression. + Expr *E; + /// \brief Helper expression of the form + /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or + /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. + Expr *UpdateExpr; + /// \brief Is 'x' a LHS in a RHS part of full update expression. It is + /// important for non-associative operations. + bool IsXLHSInRHSPart; + BinaryOperatorKind Op; + SourceLocation OpLoc; + /// \brief true if the source expression is a postfix unary operation, false + /// if it is a prefix unary operation. + bool IsPostfixUpdate; + +public: + OpenMPAtomicUpdateChecker(Sema &SemaRef) + : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr), + IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {} + /// \brief Check specified statement that it is suitable for 'atomic update' + /// constructs and extract 'x', 'expr' and Operation from the original + /// expression. If DiagId and NoteId == 0, then only check is performed + /// without error notification. + /// \param DiagId Diagnostic which should be emitted if error is found. + /// \param NoteId Diagnostic note for the main error message. + /// \return true if statement is not an update expression, false otherwise. + bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0); + /// \brief Return the 'x' lvalue part of the source atomic expression. + Expr *getX() const { return X; } + /// \brief Return the 'expr' rvalue part of the source atomic expression. + Expr *getExpr() const { return E; } + /// \brief Return the update expression used in calculation of the updated + /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or + /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. + Expr *getUpdateExpr() const { return UpdateExpr; } + /// \brief Return true if 'x' is LHS in RHS part of full update expression, + /// false otherwise. + bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } + + /// \brief true if the source expression is a postfix unary operation, false + /// if it is a prefix unary operation. + bool isPostfixUpdate() const { return IsPostfixUpdate; } + +private: + bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0, + unsigned NoteId = 0); +}; +} // namespace + +bool OpenMPAtomicUpdateChecker::checkBinaryOperation( + BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) { + ExprAnalysisErrorCode ErrorFound = NoError; + SourceLocation ErrorLoc, NoteLoc; + SourceRange ErrorRange, NoteRange; + // Allowed constructs are: + // x = x binop expr; + // x = expr binop x; + if (AtomicBinOp->getOpcode() == BO_Assign) { + X = AtomicBinOp->getLHS(); + if (auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>( + AtomicBinOp->getRHS()->IgnoreParenImpCasts())) { + if (AtomicInnerBinOp->isMultiplicativeOp() || + AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() || + AtomicInnerBinOp->isBitwiseOp()) { + Op = AtomicInnerBinOp->getOpcode(); + OpLoc = AtomicInnerBinOp->getOperatorLoc(); + auto *LHS = AtomicInnerBinOp->getLHS(); + auto *RHS = AtomicInnerBinOp->getRHS(); + llvm::FoldingSetNodeID XId, LHSId, RHSId; + X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(), + /*Canonical=*/true); + LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(), + /*Canonical=*/true); + RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(), + /*Canonical=*/true); + if (XId == LHSId) { + E = RHS; + IsXLHSInRHSPart = true; + } else if (XId == RHSId) { + E = LHS; + IsXLHSInRHSPart = false; + } else { + ErrorLoc = AtomicInnerBinOp->getExprLoc(); + ErrorRange = AtomicInnerBinOp->getSourceRange(); + NoteLoc = X->getExprLoc(); + NoteRange = X->getSourceRange(); + ErrorFound = NotAnUpdateExpression; + } + } else { + ErrorLoc = AtomicInnerBinOp->getExprLoc(); + ErrorRange = AtomicInnerBinOp->getSourceRange(); + NoteLoc = AtomicInnerBinOp->getOperatorLoc(); + NoteRange = SourceRange(NoteLoc, NoteLoc); + ErrorFound = NotABinaryOperator; + } + } else { + NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc(); + NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange(); + ErrorFound = NotABinaryExpression; + } + } else { + ErrorLoc = AtomicBinOp->getExprLoc(); + ErrorRange = AtomicBinOp->getSourceRange(); + NoteLoc = AtomicBinOp->getOperatorLoc(); + NoteRange = SourceRange(NoteLoc, NoteLoc); + ErrorFound = NotAnAssignmentOp; + } + if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { + SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; + SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; + return true; + } else if (SemaRef.CurContext->isDependentContext()) + E = X = UpdateExpr = nullptr; + return ErrorFound != NoError; +} + +bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, + unsigned NoteId) { + ExprAnalysisErrorCode ErrorFound = NoError; + SourceLocation ErrorLoc, NoteLoc; + SourceRange ErrorRange, NoteRange; + // Allowed constructs are: + // x++; + // x--; + // ++x; + // --x; + // x binop= expr; + // x = x binop expr; + // x = expr binop x; + if (auto *AtomicBody = dyn_cast<Expr>(S)) { + AtomicBody = AtomicBody->IgnoreParenImpCasts(); + if (AtomicBody->getType()->isScalarType() || + AtomicBody->isInstantiationDependent()) { + if (auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>( + AtomicBody->IgnoreParenImpCasts())) { + // Check for Compound Assignment Operation + Op = BinaryOperator::getOpForCompoundAssignment( + AtomicCompAssignOp->getOpcode()); + OpLoc = AtomicCompAssignOp->getOperatorLoc(); + E = AtomicCompAssignOp->getRHS(); + X = AtomicCompAssignOp->getLHS(); + IsXLHSInRHSPart = true; + } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>( + AtomicBody->IgnoreParenImpCasts())) { + // Check for Binary Operation + if(checkBinaryOperation(AtomicBinOp, DiagId, NoteId)) + return true; + } else if (auto *AtomicUnaryOp = + dyn_cast<UnaryOperator>(AtomicBody->IgnoreParenImpCasts())) { + // Check for Unary Operation + if (AtomicUnaryOp->isIncrementDecrementOp()) { + IsPostfixUpdate = AtomicUnaryOp->isPostfix(); + Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub; + OpLoc = AtomicUnaryOp->getOperatorLoc(); + X = AtomicUnaryOp->getSubExpr(); + E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get(); + IsXLHSInRHSPart = true; + } else { + ErrorFound = NotAnUnaryIncDecExpression; + ErrorLoc = AtomicUnaryOp->getExprLoc(); + ErrorRange = AtomicUnaryOp->getSourceRange(); + NoteLoc = AtomicUnaryOp->getOperatorLoc(); + NoteRange = SourceRange(NoteLoc, NoteLoc); + } + } else { + ErrorFound = NotABinaryOrUnaryExpression; + NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); + NoteRange = ErrorRange = AtomicBody->getSourceRange(); + } + } else { + ErrorFound = NotAScalarType; + NoteLoc = ErrorLoc = AtomicBody->getLocStart(); + NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); + } + } else { + ErrorFound = NotAnExpression; + NoteLoc = ErrorLoc = S->getLocStart(); + NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); + } + if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { + SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; + SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; + return true; + } else if (SemaRef.CurContext->isDependentContext()) + E = X = UpdateExpr = nullptr; + if (ErrorFound == NoError && E && X) { + // Build an update expression of form 'OpaqueValueExpr(x) binop + // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop + // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression. + auto *OVEX = new (SemaRef.getASTContext()) + OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_RValue); + auto *OVEExpr = new (SemaRef.getASTContext()) + OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_RValue); + auto Update = + SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr, + IsXLHSInRHSPart ? OVEExpr : OVEX); + if (Update.isInvalid()) + return true; + Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(), + Sema::AA_Casting); + if (Update.isInvalid()) + return true; + UpdateExpr = Update.get(); + } + return ErrorFound != NoError; +} + StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, @@ -3230,7 +3650,6 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, // top and a single exit at the bottom. // The point of exit cannot be a branch out of the structured block. // longjmp() and throw() must not violate the entry/exit criteria. - // TODO further analysis of associated statements and clauses. OpenMPClauseKind AtomicKind = OMPC_unknown; SourceLocation AtomicKindLoc; for (auto *C : Clauses) { @@ -3250,9 +3669,15 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } auto Body = CS->getCapturedStmt(); + if (auto *EWC = dyn_cast<ExprWithCleanups>(Body)) + Body = EWC->getSubExpr(); + Expr *X = nullptr; Expr *V = nullptr; Expr *E = nullptr; + Expr *UE = nullptr; + bool IsXLHSInRHSPart = false; + bool IsPostfixUpdate = false; // OpenMP [2.12.6, atomic Construct] // In the next expressions: // * x and v (as applicable) are both l-value expressions with scalar type. @@ -3275,14 +3700,14 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, // expr or subexpressions of expr. // * For forms that allow multiple occurrences of x, the number of times // that x is evaluated is unspecified. - enum { - NotAnExpression, - NotAnAssignmentOp, - NotAScalarType, - NotAnLValue, - NoError - } ErrorFound = NoError; if (AtomicKind == OMPC_read) { + enum { + NotAnExpression, + NotAnAssignmentOp, + NotAScalarType, + NotAnLValue, + NoError + } ErrorFound = NoError; SourceLocation ErrorLoc, NoteLoc; SourceRange ErrorRange, NoteRange; // If clause is read: @@ -3338,6 +3763,13 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } else if (CurContext->isDependentContext()) V = X = nullptr; } else if (AtomicKind == OMPC_write) { + enum { + NotAnExpression, + NotAnAssignmentOp, + NotAScalarType, + NotAnLValue, + NoError + } ErrorFound = NoError; SourceLocation ErrorLoc, NoteLoc; SourceRange ErrorRange, NoteRange; // If clause is write: @@ -3346,8 +3778,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, auto AtomicBinOp = dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { - X = AtomicBinOp->getLHS()->IgnoreParenImpCasts(); - E = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); + X = AtomicBinOp->getLHS(); + E = AtomicBinOp->getRHS(); if ((X->isInstantiationDependent() || X->getType()->isScalarType()) && (E->isInstantiationDependent() || E->getType()->isScalarType())) { if (!X->isLValue()) { @@ -3392,28 +3824,240 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } else if (CurContext->isDependentContext()) E = X = nullptr; } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) { - if (!isa<Expr>(Body)) { - Diag(Body->getLocStart(), - diag::err_omp_atomic_update_not_expression_statement) - << (AtomicKind == OMPC_update); + // If clause is update: + // x++; + // x--; + // ++x; + // --x; + // x binop= expr; + // x = x binop expr; + // x = expr binop x; + OpenMPAtomicUpdateChecker Checker(*this); + if (Checker.checkStatement( + Body, (AtomicKind == OMPC_update) + ? diag::err_omp_atomic_update_not_expression_statement + : diag::err_omp_atomic_not_expression_statement, + diag::note_omp_atomic_update)) return StmtError(); + if (!CurContext->isDependentContext()) { + E = Checker.getExpr(); + X = Checker.getX(); + UE = Checker.getUpdateExpr(); + IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); } } else if (AtomicKind == OMPC_capture) { - if (isa<Expr>(Body) && !isa<BinaryOperator>(Body)) { - Diag(Body->getLocStart(), - diag::err_omp_atomic_capture_not_expression_statement); - return StmtError(); - } else if (!isa<Expr>(Body) && !isa<CompoundStmt>(Body)) { - Diag(Body->getLocStart(), - diag::err_omp_atomic_capture_not_compound_statement); - return StmtError(); + enum { + NotAnAssignmentOp, + NotACompoundStatement, + NotTwoSubstatements, + NotASpecificExpression, + NoError + } ErrorFound = NoError; + SourceLocation ErrorLoc, NoteLoc; + SourceRange ErrorRange, NoteRange; + if (auto *AtomicBody = dyn_cast<Expr>(Body)) { + // If clause is a capture: + // v = x++; + // v = x--; + // v = ++x; + // v = --x; + // v = x binop= expr; + // v = x = x binop expr; + // v = x = expr binop x; + auto *AtomicBinOp = + dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); + if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { + V = AtomicBinOp->getLHS(); + Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); + OpenMPAtomicUpdateChecker Checker(*this); + if (Checker.checkStatement( + Body, diag::err_omp_atomic_capture_not_expression_statement, + diag::note_omp_atomic_update)) + return StmtError(); + E = Checker.getExpr(); + X = Checker.getX(); + UE = Checker.getUpdateExpr(); + IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); + IsPostfixUpdate = Checker.isPostfixUpdate(); + } else { + ErrorLoc = AtomicBody->getExprLoc(); + ErrorRange = AtomicBody->getSourceRange(); + NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() + : AtomicBody->getExprLoc(); + NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() + : AtomicBody->getSourceRange(); + ErrorFound = NotAnAssignmentOp; + } + if (ErrorFound != NoError) { + Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement) + << ErrorRange; + Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; + return StmtError(); + } else if (CurContext->isDependentContext()) { + UE = V = E = X = nullptr; + } + } else { + // If clause is a capture: + // { v = x; x = expr; } + // { v = x; x++; } + // { v = x; x--; } + // { v = x; ++x; } + // { v = x; --x; } + // { v = x; x binop= expr; } + // { v = x; x = x binop expr; } + // { v = x; x = expr binop x; } + // { x++; v = x; } + // { x--; v = x; } + // { ++x; v = x; } + // { --x; v = x; } + // { x binop= expr; v = x; } + // { x = x binop expr; v = x; } + // { x = expr binop x; v = x; } + if (auto *CS = dyn_cast<CompoundStmt>(Body)) { + // Check that this is { expr1; expr2; } + if (CS->size() == 2) { + auto *First = CS->body_front(); + auto *Second = CS->body_back(); + if (auto *EWC = dyn_cast<ExprWithCleanups>(First)) + First = EWC->getSubExpr()->IgnoreParenImpCasts(); + if (auto *EWC = dyn_cast<ExprWithCleanups>(Second)) + Second = EWC->getSubExpr()->IgnoreParenImpCasts(); + // Need to find what subexpression is 'v' and what is 'x'. + OpenMPAtomicUpdateChecker Checker(*this); + bool IsUpdateExprFound = !Checker.checkStatement(Second); + BinaryOperator *BinOp = nullptr; + if (IsUpdateExprFound) { + BinOp = dyn_cast<BinaryOperator>(First); + IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; + } + if (IsUpdateExprFound && !CurContext->isDependentContext()) { + // { v = x; x++; } + // { v = x; x--; } + // { v = x; ++x; } + // { v = x; --x; } + // { v = x; x binop= expr; } + // { v = x; x = x binop expr; } + // { v = x; x = expr binop x; } + // Check that the first expression has form v = x. + auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); + llvm::FoldingSetNodeID XId, PossibleXId; + Checker.getX()->Profile(XId, Context, /*Canonical=*/true); + PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); + IsUpdateExprFound = XId == PossibleXId; + if (IsUpdateExprFound) { + V = BinOp->getLHS(); + X = Checker.getX(); + E = Checker.getExpr(); + UE = Checker.getUpdateExpr(); + IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); + IsPostfixUpdate = true; + } + } + if (!IsUpdateExprFound) { + IsUpdateExprFound = !Checker.checkStatement(First); + BinOp = nullptr; + if (IsUpdateExprFound) { + BinOp = dyn_cast<BinaryOperator>(Second); + IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; + } + if (IsUpdateExprFound && !CurContext->isDependentContext()) { + // { x++; v = x; } + // { x--; v = x; } + // { ++x; v = x; } + // { --x; v = x; } + // { x binop= expr; v = x; } + // { x = x binop expr; v = x; } + // { x = expr binop x; v = x; } + // Check that the second expression has form v = x. + auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); + llvm::FoldingSetNodeID XId, PossibleXId; + Checker.getX()->Profile(XId, Context, /*Canonical=*/true); + PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); + IsUpdateExprFound = XId == PossibleXId; + if (IsUpdateExprFound) { + V = BinOp->getLHS(); + X = Checker.getX(); + E = Checker.getExpr(); + UE = Checker.getUpdateExpr(); + IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); + IsPostfixUpdate = false; + } + } + } + if (!IsUpdateExprFound) { + // { v = x; x = expr; } + auto *FirstBinOp = dyn_cast<BinaryOperator>(First); + if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { + ErrorFound = NotAnAssignmentOp; + NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() + : First->getLocStart(); + NoteRange = ErrorRange = FirstBinOp + ? FirstBinOp->getSourceRange() + : SourceRange(ErrorLoc, ErrorLoc); + } else { + auto *SecondBinOp = dyn_cast<BinaryOperator>(Second); + if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) { + ErrorFound = NotAnAssignmentOp; + NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc() + : Second->getLocStart(); + NoteRange = ErrorRange = SecondBinOp + ? SecondBinOp->getSourceRange() + : SourceRange(ErrorLoc, ErrorLoc); + } else { + auto *PossibleXRHSInFirst = + FirstBinOp->getRHS()->IgnoreParenImpCasts(); + auto *PossibleXLHSInSecond = + SecondBinOp->getLHS()->IgnoreParenImpCasts(); + llvm::FoldingSetNodeID X1Id, X2Id; + PossibleXRHSInFirst->Profile(X1Id, Context, /*Canonical=*/true); + PossibleXLHSInSecond->Profile(X2Id, Context, + /*Canonical=*/true); + IsUpdateExprFound = X1Id == X2Id; + if (IsUpdateExprFound) { + V = FirstBinOp->getLHS(); + X = SecondBinOp->getLHS(); + E = SecondBinOp->getRHS(); + UE = nullptr; + IsXLHSInRHSPart = false; + IsPostfixUpdate = true; + } else { + ErrorFound = NotASpecificExpression; + ErrorLoc = FirstBinOp->getExprLoc(); + ErrorRange = FirstBinOp->getSourceRange(); + NoteLoc = SecondBinOp->getLHS()->getExprLoc(); + NoteRange = SecondBinOp->getRHS()->getSourceRange(); + } + } + } + } + } else { + NoteLoc = ErrorLoc = Body->getLocStart(); + NoteRange = ErrorRange = + SourceRange(Body->getLocStart(), Body->getLocStart()); + ErrorFound = NotTwoSubstatements; + } + } else { + NoteLoc = ErrorLoc = Body->getLocStart(); + NoteRange = ErrorRange = + SourceRange(Body->getLocStart(), Body->getLocStart()); + ErrorFound = NotACompoundStatement; + } + if (ErrorFound != NoError) { + Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement) + << ErrorRange; + Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; + return StmtError(); + } else if (CurContext->isDependentContext()) { + UE = V = E = X = nullptr; + } } } getCurFunction()->setHasBranchProtectedScope(); return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, - X, V, E); + X, V, E, UE, IsXLHSInRHSPart, + IsPostfixUpdate); } StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, @@ -3655,6 +4299,9 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, << E->getSourceRange(); return ExprError(); } + if (CKind == OMPC_collapse) { + DSAStack->setCollapseNumber(Result.getExtValue()); + } return ICE; } @@ -3882,6 +4529,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( return nullptr; } Expr *ValExpr = ChunkSize; + Expr *HelperValExpr = nullptr; if (ChunkSize) { if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && !ChunkSize->isInstantiationDependent() && @@ -3898,17 +4546,25 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( // chunk_size must be a loop invariant integer expression with a positive // value. llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, Context) && - Result.isSigned() && !Result.isStrictlyPositive()) { - Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) - << "schedule" << ChunkSize->getSourceRange(); - return nullptr; + if (ValExpr->isIntegerConstantExpr(Result, Context)) { + if (Result.isSigned() && !Result.isStrictlyPositive()) { + Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) + << "schedule" << ChunkSize->getSourceRange(); + return nullptr; + } + } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { + auto *ImpVar = buildVarDecl(*this, ChunkSize->getExprLoc(), + ChunkSize->getType(), ".chunk."); + auto *ImpVarRef = buildDeclRefExpr(*this, ImpVar, ChunkSize->getType(), + ChunkSize->getExprLoc(), + /*RefersToCapture=*/true); + HelperValExpr = ImpVarRef; } } } return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, - EndLoc, Kind, ValExpr); + EndLoc, Kind, ValExpr, HelperValExpr); } OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, @@ -4133,14 +4789,6 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, continue; } - // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] - // A variable of class type (or array thereof) that appears in a private - // clause requires an accessible, unambiguous default constructor for the - // class type. - while (Type->isArrayType()) { - Type = cast<ArrayType>(Type.getTypePtr())->getElementType(); - } - // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] // Variables with the predetermined data-sharing attributes may not be @@ -4156,25 +4804,36 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, continue; } + // Variably modified types are not supported for tasks. + if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() && + DSAStack->getCurrentDirective() == OMPD_task) { + Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) + << getOpenMPClauseName(OMPC_private) << Type + << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); + bool IsDecl = + VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + continue; + } + + // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] + // A variable of class type (or array thereof) that appears in a private + // clause requires an accessible, unambiguous default constructor for the + // class type. // Generate helper private variable and initialize it with the default // value. The address of the original variable is replaced by the address of // the new private variable in CodeGen. This new variable is not added to // IdResolver, so the code in the OpenMP region uses original variable for // proper diagnostics. - auto VDPrivate = - VarDecl::Create(Context, CurContext, DE->getLocStart(), - DE->getExprLoc(), VD->getIdentifier(), VD->getType(), - VD->getTypeSourceInfo(), /*S*/ SC_Auto); - ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto*/ false); + Type = Type.getUnqualifiedType(); + auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName()); + ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); if (VDPrivate->isInvalidDecl()) continue; - CurContext->addDecl(VDPrivate); - auto VDPrivateRefExpr = - DeclRefExpr::Create(Context, /*QualifierLoc*/ NestedNameSpecifierLoc(), - /*TemplateKWLoc*/ SourceLocation(), VDPrivate, - /*RefersToEnclosingVariableOrCapture*/ false, - /*NameLoc*/ SourceLocation(), DE->getType(), - /*VK*/ VK_LValue); + auto VDPrivateRefExpr = buildDeclRefExpr( + *this, VDPrivate, DE->getType().getUnqualifiedType(), DE->getExprLoc()); DSAStack->addDSA(VD, DE, OMPC_private); Vars.push_back(DE); @@ -4285,14 +4944,12 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, // A variable of class type (or array thereof) that appears in a private // clause requires an accessible, unambiguous copy constructor for the // class type. - Type = Context.getBaseElementType(Type); + auto ElemType = Context.getBaseElementType(Type).getNonReferenceType(); // If an implicit firstprivate variable found it was checked already. if (!IsImplicitClause) { DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); - Type = Type.getNonReferenceType().getCanonicalType(); - bool IsConstant = Type.isConstant(Context); - Type = Context.getBaseElementType(Type); + bool IsConstant = ElemType.isConstant(Context); // OpenMP [2.4.13, Data-sharing Attribute Clauses] // A list item that specifies a given variable may not appear in more // than one clause on the same directive, except that a variable may be @@ -4375,10 +5032,22 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, } } + // Variably modified types are not supported for tasks. + if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() && + DSAStack->getCurrentDirective() == OMPD_task) { + Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) + << getOpenMPClauseName(OMPC_firstprivate) << Type + << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); + bool IsDecl = + VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + continue; + } + Type = Type.getUnqualifiedType(); - auto VDPrivate = VarDecl::Create(Context, CurContext, DE->getLocStart(), - ELoc, VD->getIdentifier(), VD->getType(), - VD->getTypeSourceInfo(), /*S*/ SC_Auto); + auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName()); // Generate helper private variable and initialize it with the value of the // original variable. The address of the original variable is replaced by // the address of the new private variable in the CodeGen. This new variable @@ -4387,19 +5056,16 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, Expr *VDInitRefExpr = nullptr; // For arrays generate initializer for single element and replace it by the // original array element in CodeGen. - if (DE->getType()->isArrayType()) { - auto VDInit = VarDecl::Create(Context, CurContext, DE->getLocStart(), - ELoc, VD->getIdentifier(), Type, - VD->getTypeSourceInfo(), /*S*/ SC_Auto); - CurContext->addHiddenDecl(VDInit); - VDInitRefExpr = DeclRefExpr::Create( - Context, /*QualifierLoc*/ NestedNameSpecifierLoc(), - /*TemplateKWLoc*/ SourceLocation(), VDInit, - /*RefersToEnclosingVariableOrCapture*/ true, ELoc, Type, - /*VK*/ VK_LValue); - VDInit->setIsUsed(); + if (Type->isArrayType()) { + auto VDInit = + buildVarDecl(*this, DE->getExprLoc(), ElemType, VD->getName()); + VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc); auto Init = DefaultLvalueConversion(VDInitRefExpr).get(); - InitializedEntity Entity = InitializedEntity::InitializeVariable(VDInit); + ElemType = ElemType.getUnqualifiedType(); + auto *VDInitTemp = buildVarDecl(*this, DE->getLocStart(), ElemType, + ".firstprivate.temp"); + InitializedEntity Entity = + InitializedEntity::InitializeVariable(VDInitTemp); InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc); InitializationSequence InitSeq(*this, Entity, Kind, Init); @@ -4409,15 +5075,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, else VDPrivate->setInit(Result.getAs<Expr>()); } else { - AddInitializerToDecl( - VDPrivate, - DefaultLvalueConversion( - DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), - SourceLocation(), DE->getDecl(), - /*RefersToEnclosingVariableOrCapture=*/true, - DE->getExprLoc(), DE->getType(), - /*VK=*/VK_LValue)).get(), - /*DirectInit=*/false, /*TypeMayContainAuto=*/false); + auto *VDInit = + buildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp"); + VDInitRefExpr = + buildDeclRefExpr(*this, VDInit, DE->getType(), DE->getExprLoc()); + AddInitializerToDecl(VDPrivate, + DefaultLvalueConversion(VDInitRefExpr).get(), + /*DirectInit=*/false, /*TypeMayContainAuto=*/false); } if (VDPrivate->isInvalidDecl()) { if (IsImplicitClause) { @@ -4427,12 +5091,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, continue; } CurContext->addDecl(VDPrivate); - auto VDPrivateRefExpr = - DeclRefExpr::Create(Context, /*QualifierLoc*/ NestedNameSpecifierLoc(), - /*TemplateKWLoc*/ SourceLocation(), VDPrivate, - /*RefersToEnclosingVariableOrCapture*/ false, - DE->getLocStart(), DE->getType(), - /*VK*/ VK_LValue); + auto VDPrivateRefExpr = buildDeclRefExpr( + *this, VDPrivate, DE->getType().getUnqualifiedType(), DE->getExprLoc()); DSAStack->addDSA(VD, DE, OMPC_firstprivate); Vars.push_back(DE); PrivateCopies.push_back(VDPrivateRefExpr); @@ -4451,11 +5111,17 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> SrcExprs; + SmallVector<Expr *, 8> DstExprs; + SmallVector<Expr *, 8> AssignmentOps; for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP lastprivate clause."); if (isa<DependentScopeDeclRefExpr>(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + SrcExprs.push_back(nullptr); + DstExprs.push_back(nullptr); + AssignmentOps.push_back(nullptr); continue; } @@ -4477,6 +5143,9 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); + SrcExprs.push_back(nullptr); + DstExprs.push_back(nullptr); + AssignmentOps.push_back(nullptr); continue; } @@ -4521,6 +5190,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, // lastprivate clause on a worksharing construct if any of the corresponding // worksharing regions ever binds to any of the corresponding parallel // regions. + DSAStackTy::DSAVarData TopDVar = DVar; if (isOpenMPWorksharingDirective(CurrDir) && !isOpenMPParallelDirective(CurrDir)) { DVar = DSAStack->getImplicitDSA(VD, true); @@ -4540,65 +5210,39 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, // A variable of class type (or array thereof) that appears in a // lastprivate clause requires an accessible, unambiguous copy assignment // operator for the class type. - while (Type.getNonReferenceType()->isArrayType()) - Type = cast<ArrayType>(Type.getNonReferenceType().getTypePtr()) - ->getElementType(); - CXXRecordDecl *RD = getLangOpts().CPlusPlus - ? Type.getNonReferenceType()->getAsCXXRecordDecl() - : nullptr; - // FIXME This code must be replaced by actual copying and destructing of the - // lastprivate variable. - if (RD) { - CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0); - DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess()); - if (MD) { - if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible || - MD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_lastprivate) << 2; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; - } - MarkFunctionReferenced(ELoc, MD); - DiagnoseUseOfDecl(MD, ELoc); - } - - CXXDestructorDecl *DD = RD->getDestructor(); - if (DD) { - PartialDiagnostic PD = - PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); - if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || - DD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_lastprivate) << 4; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; - } - MarkFunctionReferenced(ELoc, DD); - DiagnoseUseOfDecl(DD, ELoc); - } - } + Type = Context.getBaseElementType(Type).getNonReferenceType(); + auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), + Type.getUnqualifiedType(), ".lastprivate.src"); + auto *PseudoSrcExpr = buildDeclRefExpr( + *this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc()); + auto *DstVD = + buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst"); + auto *PseudoDstExpr = + buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc()); + // For arrays generate assignment operation for single element and replace + // it by the original array element in CodeGen. + auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, + PseudoDstExpr, PseudoSrcExpr); + if (AssignmentOp.isInvalid()) + continue; + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), + /*DiscardedValue=*/true); + if (AssignmentOp.isInvalid()) + continue; - if (DVar.CKind != OMPC_firstprivate) + if (TopDVar.CKind != OMPC_firstprivate) DSAStack->addDSA(VD, DE, OMPC_lastprivate); Vars.push_back(DE); + SrcExprs.push_back(PseudoSrcExpr); + DstExprs.push_back(PseudoDstExpr); + AssignmentOps.push_back(AssignmentOp.get()); } if (Vars.empty()) return nullptr; return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, - Vars); + Vars, SrcExprs, DstExprs, AssignmentOps); } OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, @@ -4718,19 +5362,19 @@ OMPClause *Sema::ActOnOpenMPReductionClause( switch (OOK) { case OO_Plus: case OO_Minus: - BOK = BO_AddAssign; + BOK = BO_Add; break; case OO_Star: - BOK = BO_MulAssign; + BOK = BO_Mul; break; case OO_Amp: - BOK = BO_AndAssign; + BOK = BO_And; break; case OO_Pipe: - BOK = BO_OrAssign; + BOK = BO_Or; break; case OO_Caret: - BOK = BO_XorAssign; + BOK = BO_Xor; break; case OO_AmpAmp: BOK = BO_LAnd; @@ -4738,7 +5382,44 @@ OMPClause *Sema::ActOnOpenMPReductionClause( case OO_PipePipe: BOK = BO_LOr; break; - default: + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + case OO_Slash: + case OO_Percent: + case OO_Tilde: + case OO_Exclaim: + case OO_Equal: + case OO_Less: + case OO_Greater: + case OO_LessEqual: + case OO_GreaterEqual: + case OO_PlusEqual: + case OO_MinusEqual: + case OO_StarEqual: + case OO_SlashEqual: + case OO_PercentEqual: + case OO_CaretEqual: + case OO_AmpEqual: + case OO_PipeEqual: + case OO_LessLess: + case OO_GreaterGreater: + case OO_LessLessEqual: + case OO_GreaterGreaterEqual: + case OO_EqualEqual: + case OO_ExclaimEqual: + case OO_PlusPlus: + case OO_MinusMinus: + case OO_Comma: + case OO_ArrowStar: + case OO_Arrow: + case OO_Call: + case OO_Subscript: + case OO_Conditional: + case NUM_OVERLOADED_OPERATORS: + llvm_unreachable("Unexpected reduction identifier"); + case OO_None: if (auto II = DN.getAsIdentifierInfo()) { if (II->isStr("max")) BOK = BO_GT; @@ -4760,11 +5441,17 @@ OMPClause *Sema::ActOnOpenMPReductionClause( } SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> LHSs; + SmallVector<Expr *, 8> RHSs; + SmallVector<Expr *, 8> ReductionOps; for (auto RefExpr : VarList) { assert(RefExpr && "nullptr expr in OpenMP reduction clause."); if (isa<DependentScopeDeclRefExpr>(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + LHSs.push_back(nullptr); + RHSs.push_back(nullptr); + ReductionOps.push_back(nullptr); continue; } @@ -4773,6 +5460,9 @@ OMPClause *Sema::ActOnOpenMPReductionClause( RefExpr->containsUnexpandedParameterPack()) { // It will be analyzed later. Vars.push_back(RefExpr); + LHSs.push_back(nullptr); + RHSs.push_back(nullptr); + ReductionOps.push_back(nullptr); continue; } @@ -4865,23 +5555,6 @@ OMPClause *Sema::ActOnOpenMPReductionClause( << VD; continue; } - bool Suppress = getDiagnostics().getSuppressAllDiagnostics(); - getDiagnostics().setSuppressAllDiagnostics(true); - ExprResult ReductionOp = - BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK, - RefExpr, RefExpr); - getDiagnostics().setSuppressAllDiagnostics(Suppress); - if (ReductionOp.isInvalid()) { - Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type - << ReductionIdRange; - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - continue; - } - // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] // Variables with the predetermined data-sharing attributes may not be @@ -4924,55 +5597,160 @@ OMPClause *Sema::ActOnOpenMPReductionClause( continue; } } - - CXXRecordDecl *RD = getLangOpts().CPlusPlus - ? Type.getNonReferenceType()->getAsCXXRecordDecl() - : nullptr; - // FIXME This code must be replaced by actual constructing/destructing of - // the reduction variable. - if (RD) { - CXXConstructorDecl *CD = LookupDefaultConstructor(RD); - PartialDiagnostic PD = - PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); - if (!CD || - CheckConstructorAccess(ELoc, CD, - InitializedEntity::InitializeTemporary(Type), - CD->getAccess(), PD) == AR_inaccessible || - CD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_reduction) << 0; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; + Type = Type.getNonLValueExprType(Context).getUnqualifiedType(); + auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs"); + auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName()); + // Add initializer for private variable. + Expr *Init = nullptr; + switch (BOK) { + case BO_Add: + case BO_Xor: + case BO_Or: + case BO_LOr: + // '+', '-', '^', '|', '||' reduction ops - initializer is '0'. + if (Type->isScalarType() || Type->isAnyComplexType()) { + Init = ActOnIntegerConstant(ELoc, /*Val=*/0).get(); } - MarkFunctionReferenced(ELoc, CD); - DiagnoseUseOfDecl(CD, ELoc); - - CXXDestructorDecl *DD = RD->getDestructor(); - if (DD) { - if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || - DD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_reduction) << 4; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; + break; + case BO_Mul: + case BO_LAnd: + if (Type->isScalarType() || Type->isAnyComplexType()) { + // '*' and '&&' reduction ops - initializer is '1'. + Init = ActOnIntegerConstant(ELoc, /*Val=*/1).get(); + } + break; + case BO_And: { + // '&' reduction op - initializer is '~0'. + QualType OrigType = Type; + if (auto *ComplexTy = OrigType->getAs<ComplexType>()) { + Type = ComplexTy->getElementType(); + } + if (Type->isRealFloatingType()) { + llvm::APFloat InitValue = + llvm::APFloat::getAllOnesValue(Context.getTypeSize(Type), + /*isIEEE=*/true); + Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true, + Type, ELoc); + } else if (Type->isScalarType()) { + auto Size = Context.getTypeSize(Type); + QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0); + llvm::APInt InitValue = llvm::APInt::getAllOnesValue(Size); + Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc); + } + if (Init && OrigType->isAnyComplexType()) { + // Init = 0xFFFF + 0xFFFFi; + auto *Im = new (Context) ImaginaryLiteral(Init, OrigType); + Init = CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get(); + } + Type = OrigType; + break; + } + case BO_LT: + case BO_GT: { + // 'min' reduction op - initializer is 'Largest representable number in + // the reduction list item type'. + // 'max' reduction op - initializer is 'Least representable number in + // the reduction list item type'. + if (Type->isIntegerType() || Type->isPointerType()) { + bool IsSigned = Type->hasSignedIntegerRepresentation(); + auto Size = Context.getTypeSize(Type); + QualType IntTy = + Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned); + llvm::APInt InitValue = + (BOK != BO_LT) + ? IsSigned ? llvm::APInt::getSignedMinValue(Size) + : llvm::APInt::getMinValue(Size) + : IsSigned ? llvm::APInt::getSignedMaxValue(Size) + : llvm::APInt::getMaxValue(Size); + Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc); + if (Type->isPointerType()) { + // Cast to pointer type. + auto CastExpr = BuildCStyleCastExpr( + SourceLocation(), Context.getTrivialTypeSourceInfo(Type, ELoc), + SourceLocation(), Init); + if (CastExpr.isInvalid()) + continue; + Init = CastExpr.get(); } - MarkFunctionReferenced(ELoc, DD); - DiagnoseUseOfDecl(DD, ELoc); + } else if (Type->isRealFloatingType()) { + llvm::APFloat InitValue = llvm::APFloat::getLargest( + Context.getFloatTypeSemantics(Type), BOK != BO_LT); + Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true, + Type, ELoc); + } + break; + } + case BO_PtrMemD: + case BO_PtrMemI: + case BO_MulAssign: + case BO_Div: + case BO_Rem: + case BO_Sub: + case BO_Shl: + case BO_Shr: + case BO_LE: + case BO_GE: + case BO_EQ: + case BO_NE: + case BO_AndAssign: + case BO_XorAssign: + case BO_OrAssign: + case BO_Assign: + case BO_AddAssign: + case BO_SubAssign: + case BO_DivAssign: + case BO_RemAssign: + case BO_ShlAssign: + case BO_ShrAssign: + case BO_Comma: + llvm_unreachable("Unexpected reduction operation"); + } + if (Init) { + AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false, + /*TypeMayContainAuto=*/false); + } else { + ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false); + } + if (!RHSVD->hasInit()) { + Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type + << ReductionIdRange; + bool IsDecl = + VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + continue; + } + auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc); + auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc); + ExprResult ReductionOp = + BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK, + LHSDRE, RHSDRE); + if (ReductionOp.isUsable()) { + if (BOK != BO_LT && BOK != BO_GT) { + ReductionOp = + BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), + BO_Assign, LHSDRE, ReductionOp.get()); + } else { + auto *ConditionalOp = new (Context) ConditionalOperator( + ReductionOp.get(), SourceLocation(), LHSDRE, SourceLocation(), + RHSDRE, Type, VK_LValue, OK_Ordinary); + ReductionOp = + BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), + BO_Assign, LHSDRE, ConditionalOp); + } + if (ReductionOp.isUsable()) { + ReductionOp = ActOnFinishFullExpr(ReductionOp.get()); } } + if (ReductionOp.isInvalid()) + continue; DSAStack->addDSA(VD, DE, OMPC_reduction); Vars.push_back(DE); + LHSs.push_back(LHSDRE); + RHSs.push_back(RHSDRE); + ReductionOps.push_back(ReductionOp.get()); } if (Vars.empty()) @@ -4980,7 +5758,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause( return OMPReductionClause::Create( Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars, - ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId); + ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, LHSs, + RHSs, ReductionOps); } OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, @@ -4989,11 +5768,13 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, SourceLocation ColonLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> Inits; for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP linear clause."); if (isa<DependentScopeDeclRefExpr>(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + Inits.push_back(nullptr); continue; } @@ -5035,6 +5816,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, if (QType->isDependentType() || QType->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); + Inits.push_back(nullptr); continue; } @@ -5080,14 +5862,22 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, continue; } + // Build var to save initial value. + VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start"); + AddInitializerToDecl(Init, DefaultLvalueConversion(DE).get(), + /*DirectInit*/ false, /*TypeMayContainAuto*/ false); + auto InitRef = buildDeclRefExpr( + *this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc()); DSAStack->addDSA(VD, DE, OMPC_linear); Vars.push_back(DE); + Inits.push_back(InitRef); } if (Vars.empty()) return nullptr; Expr *StepExpr = Step; + Expr *CalcStepExpr = nullptr; if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && !Step->isInstantiationDependent() && !Step->containsUnexpandedParameterPack()) { @@ -5097,17 +5887,82 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, return nullptr; StepExpr = Val.get(); + // Build var to save the step value. + VarDecl *SaveVar = + buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step"); + ExprResult SaveRef = + buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); + ExprResult CalcStep = + BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); + // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). llvm::APSInt Result; - if (StepExpr->isIntegerConstantExpr(Result, Context) && - !Result.isNegative() && !Result.isStrictlyPositive()) + bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context); + if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive()) Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0] << (Vars.size() > 1); + if (!IsConstant && CalcStep.isUsable()) { + // Calculate the step beforehand instead of doing this on each iteration. + // (This is not used if the number of iterations may be kfold-ed). + CalcStepExpr = CalcStep.get(); + } } return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc, - Vars, StepExpr); + Vars, Inits, StepExpr, CalcStepExpr); +} + +static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, + Expr *NumIterations, Sema &SemaRef, + Scope *S) { + // Walk the vars and build update/final expressions for the CodeGen. + SmallVector<Expr *, 8> Updates; + SmallVector<Expr *, 8> Finals; + Expr *Step = Clause.getStep(); + Expr *CalcStep = Clause.getCalcStep(); + // OpenMP [2.14.3.7, linear clause] + // If linear-step is not specified it is assumed to be 1. + if (Step == nullptr) + Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); + else if (CalcStep) + Step = cast<BinaryOperator>(CalcStep)->getLHS(); + bool HasErrors = false; + auto CurInit = Clause.inits().begin(); + for (auto &RefExpr : Clause.varlists()) { + Expr *InitExpr = *CurInit; + + // Build privatized reference to the current linear var. + auto DE = cast<DeclRefExpr>(RefExpr); + auto PrivateRef = + buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()), + DE->getType().getUnqualifiedType(), DE->getExprLoc(), + /*RefersToCapture=*/true); + + // Build update: Var = InitExpr + IV * Step + ExprResult Update = + BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef, + InitExpr, IV, Step, /* Subtract */ false); + Update = SemaRef.ActOnFinishFullExpr(Update.get()); + + // Build final: Var = InitExpr + NumIterations * Step + ExprResult Final = + BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef, + InitExpr, NumIterations, Step, /* Subtract */ false); + Final = SemaRef.ActOnFinishFullExpr(Final.get()); + if (!Update.isUsable() || !Final.isUsable()) { + Updates.push_back(nullptr); + Finals.push_back(nullptr); + HasErrors = true; + } else { + Updates.push_back(Update.get()); + Finals.push_back(Final.get()); + } + ++CurInit; + } + Clause.setUpdates(Updates); + Clause.setFinals(Finals); + return HasErrors; } OMPClause *Sema::ActOnOpenMPAlignedClause( @@ -5137,10 +5992,8 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( // OpenMP [2.8.1, simd construct, Restrictions] // The type of list items appearing in the aligned clause must be // array, pointer, reference to array, or reference to pointer. - QualType QType = DE->getType() - .getNonReferenceType() - .getUnqualifiedType() - .getCanonicalType(); + QualType QType = VD->getType(); + QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType(); const Type *Ty = QType.getTypePtrOrNull(); if (!Ty || (!Ty->isDependentType() && !Ty->isArrayType() && !Ty->isPointerType())) { @@ -5190,11 +6043,17 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> SrcExprs; + SmallVector<Expr *, 8> DstExprs; + SmallVector<Expr *, 8> AssignmentOps; for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP copyin clause."); if (isa<DependentScopeDeclRefExpr>(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + SrcExprs.push_back(nullptr); + DstExprs.push_back(nullptr); + AssignmentOps.push_back(nullptr); continue; } @@ -5216,6 +6075,9 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); + SrcExprs.push_back(nullptr); + DstExprs.push_back(nullptr); + AssignmentOps.push_back(nullptr); continue; } @@ -5232,40 +6094,38 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, // A variable of class type (or array thereof) that appears in a // copyin clause requires an accessible, unambiguous copy assignment // operator for the class type. - Type = Context.getBaseElementType(Type); - CXXRecordDecl *RD = - getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; - // FIXME This code must be replaced by actual assignment of the - // threadprivate variable. - if (RD) { - CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0); - DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess()); - if (MD) { - if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible || - MD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_copyin) << 2; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; - } - MarkFunctionReferenced(ELoc, MD); - DiagnoseUseOfDecl(MD, ELoc); - } - } + auto ElemType = Context.getBaseElementType(Type).getNonReferenceType(); + auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), + ElemType.getUnqualifiedType(), ".copyin.src"); + auto *PseudoSrcExpr = buildDeclRefExpr( + *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc()); + auto *DstVD = + buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst"); + auto *PseudoDstExpr = + buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc()); + // For arrays generate assignment operation for single element and replace + // it by the original array element in CodeGen. + auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, + PseudoDstExpr, PseudoSrcExpr); + if (AssignmentOp.isInvalid()) + continue; + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), + /*DiscardedValue=*/true); + if (AssignmentOp.isInvalid()) + continue; DSAStack->addDSA(VD, DE, OMPC_copyin); Vars.push_back(DE); + SrcExprs.push_back(PseudoSrcExpr); + DstExprs.push_back(PseudoDstExpr); + AssignmentOps.push_back(AssignmentOp.get()); } if (Vars.empty()) return nullptr; - return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); + return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, + SrcExprs, DstExprs, AssignmentOps); } OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, @@ -5273,11 +6133,17 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> SrcExprs; + SmallVector<Expr *, 8> DstExprs; + SmallVector<Expr *, 8> AssignmentOps; for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP copyprivate clause."); if (isa<DependentScopeDeclRefExpr>(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + SrcExprs.push_back(nullptr); + DstExprs.push_back(nullptr); + AssignmentOps.push_back(nullptr); continue; } @@ -5299,6 +6165,9 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); + SrcExprs.push_back(nullptr); + DstExprs.push_back(nullptr); + AssignmentOps.push_back(nullptr); continue; } @@ -5307,8 +6176,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, // private or firstprivate clause on the single construct. if (!DSAStack->isThreadPrivate(VD)) { auto DVar = DSAStack->getTopDSA(VD, false); - if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown && - !(DVar.CKind == OMPC_private && !DVar.RefExpr)) { + if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate && + DVar.RefExpr) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_copyprivate); @@ -5331,45 +6200,54 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, } } + // Variably modified types are not supported. + if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) { + Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) + << getOpenMPClauseName(OMPC_copyprivate) << Type + << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); + bool IsDecl = + VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + continue; + } + // OpenMP [2.14.4.1, Restrictions, C/C++, p.2] // A variable of class type (or array thereof) that appears in a // copyin clause requires an accessible, unambiguous copy assignment // operator for the class type. - Type = Context.getBaseElementType(Type); - CXXRecordDecl *RD = - getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; - // FIXME This code must be replaced by actual assignment of the - // threadprivate variable. - if (RD) { - CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0); - DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess()); - if (MD) { - if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible || - MD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_copyprivate) << 2; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; - } - MarkFunctionReferenced(ELoc, MD); - DiagnoseUseOfDecl(MD, ELoc); - } - } + Type = Context.getBaseElementType(Type).getUnqualifiedType(); + auto *SrcVD = + buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src"); + auto *PseudoSrcExpr = + buildDeclRefExpr(*this, SrcVD, Type, DE->getExprLoc()); + auto *DstVD = + buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst"); + auto *PseudoDstExpr = + buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc()); + auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, + PseudoDstExpr, PseudoSrcExpr); + if (AssignmentOp.isInvalid()) + continue; + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), + /*DiscardedValue=*/true); + if (AssignmentOp.isInvalid()) + continue; // No need to mark vars as copyprivate, they are already threadprivate or // implicitly private. Vars.push_back(DE); + SrcExprs.push_back(PseudoSrcExpr); + DstExprs.push_back(PseudoDstExpr); + AssignmentOps.push_back(AssignmentOp.get()); } if (Vars.empty()) return nullptr; - return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); + return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, + Vars, SrcExprs, DstExprs, AssignmentOps); } OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 9195ee5..9d87a10 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -286,6 +286,16 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, QualType FromType = getToType(0); QualType ToType = getToType(1); switch (Second) { + // 'bool' is an integral type; dispatch to the right place to handle it. + case ICK_Boolean_Conversion: + if (FromType->isRealFloatingType()) + goto FloatingIntegralConversion; + if (FromType->isIntegralOrUnscopedEnumerationType()) + goto IntegralConversion; + // Boolean conversions can be from pointers and pointers to members + // [conv.bool], and those aren't considered narrowing conversions. + return NK_Not_Narrowing; + // -- from a floating-point type to an integer type, or // // -- from an integer type or unscoped enumeration type to a floating-point @@ -293,6 +303,7 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, // value after conversion will fit into the target type and will produce // the original value when converted back to the original type, or case ICK_Floating_Integral: + FloatingIntegralConversion: if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) { return NK_Type_Narrowing; } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) { @@ -357,13 +368,8 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, // the source is a constant expression and the actual value after // conversion will fit into the target type and will produce the original // value when converted back to the original type. - case ICK_Boolean_Conversion: // Bools are integers too. - if (!FromType->isIntegralOrUnscopedEnumerationType()) { - // Boolean conversions can be from pointers and pointers to members - // [conv.bool], and those aren't considered narrowing conversions. - return NK_Not_Narrowing; - } // Otherwise, fall through to the integral case. - case ICK_Integral_Conversion: { + case ICK_Integral_Conversion: + IntegralConversion: { assert(FromType->isIntegralOrUnscopedEnumerationType()); assert(ToType->isIntegralOrUnscopedEnumerationType()); const bool FromSigned = FromType->isSignedIntegerOrEnumerationType(); @@ -1098,11 +1104,11 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Attempt user-defined conversion. OverloadCandidateSet Conversions(From->getExprLoc(), OverloadCandidateSet::CSK_Normal); - OverloadingResult UserDefResult - = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions, - AllowExplicit, AllowObjCConversionOnExplicit); - - if (UserDefResult == OR_Success) { + switch (IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, + Conversions, AllowExplicit, + AllowObjCConversionOnExplicit)) { + case OR_Success: + case OR_Deleted: ICS.setUserDefined(); ICS.UserDefined.Before.setAsIdentityConversion(); // C++ [over.ics.user]p4: @@ -1131,7 +1137,9 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, ICS.Standard.Second = ICK_Derived_To_Base; } } - } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) { + break; + + case OR_Ambiguous: ICS.setAmbiguous(); ICS.Ambiguous.setFromType(From->getType()); ICS.Ambiguous.setToType(ToType); @@ -1139,8 +1147,12 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, Cand != Conversions.end(); ++Cand) if (Cand->Viable) ICS.Ambiguous.addConversion(Cand->Function); - } else { + break; + + // Fall through. + case OR_No_Viable_Function: ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + break; } return ICS; @@ -1740,18 +1752,20 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { return false; // We can perform an integral promotion to the underlying type of the enum, - // even if that's not the promoted type. + // even if that's not the promoted type. Note that the check for promoting + // the underlying type is based on the type alone, and does not consider + // the bitfield-ness of the actual source expression. if (FromEnumType->getDecl()->isFixed()) { QualType Underlying = FromEnumType->getDecl()->getIntegerType(); return Context.hasSameUnqualifiedType(Underlying, ToType) || - IsIntegralPromotion(From, Underlying, ToType); + IsIntegralPromotion(nullptr, Underlying, ToType); } // We have already pre-calculated the promotion type, so this is trivial. if (ToType->isIntegerType() && !RequireCompleteType(From->getLocStart(), FromType, 0)) - return Context.hasSameUnqualifiedType(ToType, - FromEnumType->getDecl()->getPromotionType()); + return Context.hasSameUnqualifiedType( + ToType, FromEnumType->getDecl()->getPromotionType()); } // C++0x [conv.prom]p2: @@ -1799,13 +1813,12 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // other value of that type for promotion purposes (C++ 4.5p3). // FIXME: We should delay checking of bit-fields until we actually perform the // conversion. - using llvm::APSInt; - if (From) + if (From) { if (FieldDecl *MemberDecl = From->getSourceBitField()) { - APSInt BitWidth; + llvm::APSInt BitWidth; if (FromType->isIntegralType(Context) && MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { - APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); + llvm::APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); ToSize = Context.getTypeSize(ToType); // Are we promoting to an int from a bitfield that fits in an int? @@ -1823,6 +1836,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { return false; } } + } // An rvalue of type bool can be converted to an rvalue of type int, // with false becoming zero and true becoming one (C++ 4.5p4). @@ -2940,7 +2954,10 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, bool HadMultipleCandidates = (CandidateSet.size() > 1); OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { + switch (auto Result = + CandidateSet.BestViableFunction(S, From->getLocStart(), + Best, true)) { + case OR_Deleted: case OR_Success: { // Record the standard conversion we used and the conversion function. CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); @@ -2953,13 +2970,11 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, User.After.setAsIdentityConversion(); User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); User.After.setAllToTypes(ToType); - return OR_Success; + return Result; } case OR_No_Viable_Function: return OR_No_Viable_Function; - case OR_Deleted: - return OR_Deleted; case OR_Ambiguous: return OR_Ambiguous; } @@ -3093,11 +3108,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, if (CXXRecordDecl *FromRecordDecl = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) { // Add all of the conversion functions as candidates. - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> - Conversions = FromRecordDecl->getVisibleConversionFunctions(); - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { + const auto &Conversions = FromRecordDecl->getVisibleConversionFunctions(); + for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { DeclAccessPair FoundDecl = I.getPair(); NamedDecl *D = FoundDecl.getDecl(); CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); @@ -3129,8 +3141,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, bool HadMultipleCandidates = (CandidateSet.size() > 1); OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { + switch (auto Result = CandidateSet.BestViableFunction(S, From->getLocStart(), + Best, true)) { case OR_Success: + case OR_Deleted: // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Best->Function)) { @@ -3158,7 +3172,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, User.After.setAsIdentityConversion(); User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); User.After.setAllToTypes(ToType); - return OR_Success; + return Result; } if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(Best->Function)) { @@ -3184,15 +3198,12 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // user-defined conversion sequence (see 13.3.3 and // 13.3.3.1). User.After = Best->FinalConversion; - return OR_Success; + return Result; } llvm_unreachable("Not a constructor or conversion function?"); case OR_No_Viable_Function: return OR_No_Viable_Function; - case OR_Deleted: - // No conversion here! We're done. - return OR_Deleted; case OR_Ambiguous: return OR_Ambiguous; @@ -3329,7 +3340,26 @@ CompareImplicitConversionSequences(Sema &S, // Two implicit conversion sequences of the same form are // indistinguishable conversion sequences unless one of the // following rules apply: (C++ 13.3.3.2p3): + + // List-initialization sequence L1 is a better conversion sequence than + // list-initialization sequence L2 if: + // - L1 converts to std::initializer_list<X> for some X and L2 does not, or, + // if not that, + // - L1 converts to type "array of N1 T", L2 converts to type "array of N2 T", + // and N1 is smaller than N2., + // even if one of the other rules in this paragraph would otherwise apply. + if (!ICS1.isBad()) { + if (ICS1.isStdInitializerListElement() && + !ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Better; + if (!ICS1.isStdInitializerListElement() && + ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Worse; + } + if (ICS1.isStandard()) + // Standard conversion sequence S1 is a better conversion sequence than + // standard conversion sequence S2 if [...] Result = CompareStandardConversionSequences(S, ICS1.Standard, ICS2.Standard); else if (ICS1.isUserDefined()) { @@ -3350,19 +3380,6 @@ CompareImplicitConversionSequences(Sema &S, ICS2.UserDefined.ConversionFunction); } - // List-initialization sequence L1 is a better conversion sequence than - // list-initialization sequence L2 if L1 converts to std::initializer_list<X> - // for some X and L2 does not. - if (Result == ImplicitConversionSequence::Indistinguishable && - !ICS1.isBad()) { - if (ICS1.isStdInitializerListElement() && - !ICS2.isStdInitializerListElement()) - return ImplicitConversionSequence::Better; - if (!ICS1.isStdInitializerListElement() && - ICS2.isStdInitializerListElement()) - return ImplicitConversionSequence::Worse; - } - return Result; } @@ -4034,11 +4051,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); OverloadCandidateSet CandidateSet(DeclLoc, OverloadCandidateSet::CSK_Normal); - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> - Conversions = T2RecordDecl->getVisibleConversionFunctions(); - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { + const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions(); + for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) @@ -4254,16 +4268,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // -- Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference // shall be an rvalue reference. - // - // We actually handle one oddity of C++ [over.ics.ref] at this - // point, which is that, due to p2 (which short-circuits reference - // binding by only attempting a simple conversion for non-direct - // bindings) and p3's strange wording, we allow a const volatile - // reference to bind to an rvalue. Hence the check for the presence - // of "const" rather than checking for "const" being the only - // qualifier. - // This is also the point where rvalue references and lvalue inits no longer - // go together. if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified())) return ICS; @@ -4456,11 +4460,57 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, if (S.RequireCompleteType(From->getLocStart(), ToType, 0)) return Result; + // Per DR1467: + // If the parameter type is a class X and the initializer list has a single + // element of type cv U, where U is X or a class derived from X, the + // implicit conversion sequence is the one required to convert the element + // to the parameter type. + // + // Otherwise, if the parameter type is a character array [... ] + // and the initializer list has a single element that is an + // appropriately-typed string literal (8.5.2 [dcl.init.string]), the + // implicit conversion sequence is the identity conversion. + if (From->getNumInits() == 1) { + if (ToType->isRecordType()) { + QualType InitType = From->getInit(0)->getType(); + if (S.Context.hasSameUnqualifiedType(InitType, ToType) || + S.IsDerivedFrom(InitType, ToType)) + return TryCopyInitialization(S, From->getInit(0), ToType, + SuppressUserConversions, + InOverloadResolution, + AllowObjCWritebackConversion); + } + // FIXME: Check the other conditions here: array of character type, + // initializer is a string literal. + if (ToType->isArrayType()) { + InitializedEntity Entity = + InitializedEntity::InitializeParameter(S.Context, ToType, + /*Consumed=*/false); + if (S.CanPerformCopyInitialization(Entity, From)) { + Result.setStandard(); + Result.Standard.setAsIdentityConversion(); + Result.Standard.setFromType(ToType); + Result.Standard.setAllToTypes(ToType); + return Result; + } + } + } + + // C++14 [over.ics.list]p2: Otherwise, if the parameter type [...] (below). // C++11 [over.ics.list]p2: // If the parameter type is std::initializer_list<X> or "array of X" and // all the elements can be implicitly converted to X, the implicit // conversion sequence is the worst conversion necessary to convert an // element of the list to X. + // + // C++14 [over.ics.list]p3: + // Otherwise, if the parameter type is "array of N X", if the initializer + // list has exactly N elements or if it has fewer than N elements and X is + // default-constructible, and if all the elements of the initializer list + // can be implicitly converted to X, the implicit conversion sequence is + // the worst conversion necessary to convert an element of the list to X. + // + // FIXME: We're missing a lot of these checks. bool toStdInitializerList = false; QualType X; if (ToType->isArrayType()) @@ -4499,6 +4549,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, return Result; } + // C++14 [over.ics.list]p4: // C++11 [over.ics.list]p3: // Otherwise, if the parameter is a non-aggregate class X and overload // resolution chooses a single best constructor [...] the implicit @@ -4514,6 +4565,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, /*AllowObjCConversionOnExplicit=*/false); } + // C++14 [over.ics.list]p5: // C++11 [over.ics.list]p4: // Otherwise, if the parameter has an aggregate type which can be // initialized from the initializer list [...] the implicit conversion @@ -4540,6 +4592,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, return Result; } + // C++14 [over.ics.list]p6: // C++11 [over.ics.list]p5: // Otherwise, if the parameter is a reference, see 13.3.3.1.4. if (ToType->isReferenceType()) { @@ -4608,14 +4661,15 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, return Result; } + // C++14 [over.ics.list]p7: // C++11 [over.ics.list]p6: // Otherwise, if the parameter type is not a class: if (!ToType->isRecordType()) { - // - if the initializer list has one element, the implicit conversion - // sequence is the one required to convert the element to the - // parameter type. + // - if the initializer list has one element that is not itself an + // initializer list, the implicit conversion sequence is the one + // required to convert the element to the parameter type. unsigned NumInits = From->getNumInits(); - if (NumInits == 1) + if (NumInits == 1 && !isa<InitListExpr>(From->getInit(0))) Result = TryCopyInitialization(S, From->getInit(0), ToType, SuppressUserConversions, InOverloadResolution, @@ -4631,6 +4685,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, return Result; } + // C++14 [over.ics.list]p8: // C++11 [over.ics.list]p7: // In all cases other than those enumerated above, no conversion is possible return Result; @@ -5347,21 +5402,18 @@ ExprResult Sema::PerformContextualImplicitConversion( UnresolvedSet<4> ViableConversions; // These are *potentially* viable in C++1y. UnresolvedSet<4> ExplicitConversions; - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> Conversions = + const auto &Conversions = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); bool HadMultipleCandidates = - (std::distance(Conversions.first, Conversions.second) > 1); + (std::distance(Conversions.begin(), Conversions.end()) > 1); // To check that there is only one target type, in C++1y: QualType ToType; bool HasUniqueTargetType = true; // Collect explicit or viable (potentially in C++1y) conversions. - for (CXXRecordDecl::conversion_iterator I = Conversions.first, - E = Conversions.second; - I != E; ++I) { + for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); CXXConversionDecl *Conversion; FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D); @@ -5554,7 +5606,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // is irrelevant. AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), - Args, CandidateSet, SuppressUserConversions); + Args, CandidateSet, SuppressUserConversions, + PartialOverloading); return; } // We treat a constructor like a non-member function, since its object @@ -5615,7 +5668,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // (C++ 13.3.2p2): A candidate function having fewer than m // parameters is viable only if it has an ellipsis in its parameter // list (8.3.5). - if ((Args.size() + (PartialOverloading && Args.size())) > NumParams && + if (TooManyArguments(NumParams, Args.size(), PartialOverloading) && !Proto->isVariadic()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_many_arguments; @@ -5850,8 +5903,9 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs, bool SuppressUserConversions, - TemplateArgumentListInfo *ExplicitTemplateArgs) { + bool PartialOverloading) { for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { NamedDecl *D = F.getDecl()->getUnderlyingDecl(); if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -5860,10 +5914,10 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, cast<CXXMethodDecl>(FD)->getParent(), Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), CandidateSet, - SuppressUserConversions); + SuppressUserConversions, PartialOverloading); else AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet, - SuppressUserConversions); + SuppressUserConversions, PartialOverloading); } else { FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && @@ -5873,11 +5927,13 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ExplicitTemplateArgs, Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + PartialOverloading); else AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs, Args, - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + PartialOverloading); } } } @@ -5925,7 +5981,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions) { + bool SuppressUserConversions, + bool PartialOverloading) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -5958,7 +6015,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // (C++ 13.3.2p2): A candidate function having fewer than m // parameters is viable only if it has an ellipsis in its parameter // list (8.3.5). - if (Args.size() > NumParams && !Proto->isVariadic()) { + if (TooManyArguments(NumParams, Args.size(), PartialOverloading) && + !Proto->isVariadic()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_many_arguments; return; @@ -5970,7 +6028,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // parameter list is truncated on the right, so that there are // exactly m parameters. unsigned MinRequiredArgs = Method->getMinRequiredArguments(); - if (Args.size() < MinRequiredArgs) { + if (Args.size() < MinRequiredArgs && !PartialOverloading) { // Not enough arguments. Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_few_arguments; @@ -6052,7 +6110,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions) { + bool SuppressUserConversions, + bool PartialOverloading) { if (!CandidateSet.isNewCandidate(MethodTmpl)) return; @@ -6069,7 +6128,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult Result = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, - Specialization, Info)) { + Specialization, Info, PartialOverloading)) { OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = MethodTmpl->getTemplatedDecl(); @@ -6090,7 +6149,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, "Specialization is not a member function?"); AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, PartialOverloading); } /// \brief Add a C++ function template specialization as a candidate @@ -6102,7 +6161,8 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions) { + bool SuppressUserConversions, + bool PartialOverloading) { if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; @@ -6119,7 +6179,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, - Specialization, Info)) { + Specialization, Info, PartialOverloading)) { OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); @@ -6137,7 +6197,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, - SuppressUserConversions); + SuppressUserConversions, PartialOverloading); } /// Determine whether this is an allowable conversion from the result @@ -6884,12 +6944,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, return; CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> - Conversions = ClassDecl->getVisibleConversionFunctions(); - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { - NamedDecl *D = I.getDecl(); + for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) { if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); @@ -6953,13 +7008,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { if (!ClassDecl->hasDefinition()) return VRQuals; - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> - Conversions = ClassDecl->getVisibleConversionFunctions(); - - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { - NamedDecl *D = I.getDecl(); + for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) { if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) { @@ -8078,7 +8127,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, bool HasArithmeticOrEnumeralCandidateType = false; SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes; for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) { - CandidateTypes.push_back(BuiltinCandidateTypeSet(*this)); + CandidateTypes.emplace_back(*this); CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(), OpLoc, true, @@ -8291,7 +8340,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, } else AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, - Args, CandidateSet); + Args, CandidateSet, PartialOverloading); } } @@ -9451,10 +9500,7 @@ struct CompareOverloadCandidatesForDisplay { numLFixes = (numLFixes == 0) ? UINT_MAX : numLFixes; numRFixes = (numRFixes == 0) ? UINT_MAX : numRFixes; if (numLFixes != numRFixes) { - if (numLFixes < numRFixes) - return true; - else - return false; + return numLFixes < numRFixes; } // If there's any ordering between the defined conversions... @@ -10363,7 +10409,8 @@ static void AddOverloadedCallCandidate(Sema &S, assert(!KnownValid && "Explicit template arguments?"); return; } - S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, false, + S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, + /*SuppressUsedConversions=*/false, PartialOverloading); return; } @@ -10371,7 +10418,9 @@ static void AddOverloadedCallCandidate(Sema &S, if (FunctionTemplateDecl *FuncTemplate = dyn_cast<FunctionTemplateDecl>(Callee)) { S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl, - ExplicitTemplateArgs, Args, CandidateSet); + ExplicitTemplateArgs, Args, CandidateSet, + /*SuppressUsedConversions=*/false, + PartialOverloading); return; } @@ -10896,7 +10945,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, ArgsArray, CandidateSet, false); + AddFunctionCandidates(Fns, ArgsArray, CandidateSet); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); @@ -11105,7 +11154,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, Args, CandidateSet, false); + AddFunctionCandidates(Fns, Args, CandidateSet); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet); @@ -11546,6 +11595,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, return MaybeBindToTemporary(call); } + if (isa<CXXPseudoDestructorExpr>(NakedMemExpr)) + return new (Context) + CallExpr(Context, MemExprE, Args, Context.VoidTy, VK_RValue, RParenLoc); + UnbridgedCastsSet UnbridgedCasts; if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) return ExprError(); @@ -11805,11 +11858,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // functions for each conversion function declared in an // accessible base class provided the function is not hidden // within T by another intervening declaration. - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> Conversions - = cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions(); - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { + const auto &Conversions = + cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions(); + for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) @@ -12154,8 +12205,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, OverloadCandidateSet CandidateSet(UDSuffixLoc, OverloadCandidateSet::CSK_Normal); - AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true, - TemplateArgs); + AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, TemplateArgs, + /*SuppressUserConversions=*/true); bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -12440,15 +12491,11 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, type = Context.BoundMemberTy; } - MemberExpr *ME = MemberExpr::Create(Context, Base, - MemExpr->isArrow(), - MemExpr->getQualifierLoc(), - MemExpr->getTemplateKeywordLoc(), - Fn, - Found, - MemExpr->getMemberNameInfo(), - TemplateArgs, - type, valueKind, OK_Ordinary); + MemberExpr *ME = MemberExpr::Create( + Context, Base, MemExpr->isArrow(), MemExpr->getOperatorLoc(), + MemExpr->getQualifierLoc(), MemExpr->getTemplateKeywordLoc(), Fn, Found, + MemExpr->getMemberNameInfo(), TemplateArgs, type, valueKind, + OK_Ordinary); ME->setHadMultipleCandidates(true); MarkMemberReferenced(ME); return ME; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp index 5e92d5d..3e465af 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp @@ -1051,17 +1051,13 @@ Sema::ObjCSubscriptKind // Look for a conversion to an integral, enumeration type, or // objective-C pointer type. - std::pair<CXXRecordDecl::conversion_iterator, - CXXRecordDecl::conversion_iterator> Conversions - = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); - int NoIntegrals=0, NoObjCIdPointers=0; SmallVector<CXXConversionDecl *, 4> ConversionDecls; - - for (CXXRecordDecl::conversion_iterator - I = Conversions.first, E = Conversions.second; I != E; ++I) { - if (CXXConversionDecl *Conversion - = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { + + for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl()) + ->getVisibleConversionFunctions()) { + if (CXXConversionDecl *Conversion = + dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) { QualType CT = Conversion->getConversionType().getNonReferenceType(); if (CT->isIntegralOrEnumerationType()) { ++NoIntegrals; @@ -1196,7 +1192,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { AtIndexGetter = S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, RefExpr->getSourceRange(), - true, false); + true); } if (AtIndexGetter) { @@ -1318,7 +1314,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { AtIndexSetter = S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, RefExpr->getSourceRange(), - true, false); + true); } bool err = false; @@ -1446,7 +1442,7 @@ ExprResult MSPropertyOpBuilder::buildGet() { ExprResult GetterExpr = S.ActOnMemberAccessExpr( S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), - GetterName, nullptr, true); + GetterName, nullptr); if (GetterExpr.isInvalid()) { S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_accessor) << 0 /* getter */ @@ -1476,7 +1472,7 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, ExprResult SetterExpr = S.ActOnMemberAccessExpr( S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), - SetterName, nullptr, true); + SetterName, nullptr); if (SetterExpr.isInvalid()) { S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_accessor) << 1 /* setter */ diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 0d1da45..5c72529 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/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" @@ -23,12 +24,14 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeOrdering.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -236,7 +239,9 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { // is written in a macro body, only warn if it has the warn_unused_result // attribute. if (const Decl *FD = CE->getCalleeDecl()) { - if (FD->hasAttr<WarnUnusedResultAttr>()) { + const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD); + if (Func ? Func->hasUnusedResultAttr() + : FD->hasAttr<WarnUnusedResultAttr>()) { Diag(Loc, diag::warn_unused_result) << R1 << R2; return; } @@ -265,10 +270,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { Diag(Loc, diag::warn_unused_result) << R1 << R2; return; } - if (MD->isPropertyAccessor()) { - Diag(Loc, diag::warn_unused_property_expr); - return; - } } } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { const Expr *Source = POE->getSyntacticForm(); @@ -687,26 +688,39 @@ static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val, } } +typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy; + /// Returns true if we should emit a diagnostic about this case expression not /// being a part of the enum used in the switch controlling expression. -static bool ShouldDiagnoseSwitchCaseNotInEnum(const ASTContext &Ctx, +static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, const EnumDecl *ED, - const Expr *CaseExpr) { - // Don't warn if the 'case' expression refers to a static const variable of - // the enum type. - CaseExpr = CaseExpr->IgnoreParenImpCasts(); - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseExpr)) { + const Expr *CaseExpr, + EnumValsTy::iterator &EI, + EnumValsTy::iterator &EIEnd, + const llvm::APSInt &Val) { + bool FlagType = ED->hasAttr<FlagEnumAttr>(); + + if (const DeclRefExpr *DRE = + dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) { if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { - if (!VD->hasGlobalStorage()) - return true; QualType VarType = VD->getType(); - if (!VarType.isConstQualified()) - return true; - QualType EnumType = Ctx.getTypeDeclType(ED); - if (Ctx.hasSameUnqualifiedType(EnumType, VarType)) + QualType EnumType = S.Context.getTypeDeclType(ED); + if (VD->hasGlobalStorage() && VarType.isConstQualified() && + S.Context.hasSameUnqualifiedType(EnumType, VarType)) return false; } } + + if (FlagType) { + return !S.IsValueInFlagEnum(ED, Val, false); + } else { + while (EI != EIEnd && EI->first < Val) + EI++; + + if (EI != EIEnd && EI->first == Val) + return false; + } + return true; } @@ -897,12 +911,12 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (PrevString == CurrString) Diag(CaseVals[i].second->getLHS()->getLocStart(), diag::err_duplicate_case) << - (PrevString.empty() ? CaseValStr.str() : PrevString); + (PrevString.empty() ? StringRef(CaseValStr) : PrevString); else Diag(CaseVals[i].second->getLHS()->getLocStart(), diag::err_duplicate_case_differing_expr) << - (PrevString.empty() ? CaseValStr.str() : PrevString) << - (CurrString.empty() ? CaseValStr.str() : CurrString) << + (PrevString.empty() ? StringRef(CaseValStr) : PrevString) << + (CurrString.empty() ? StringRef(CaseValStr) : CurrString) << CaseValStr; Diag(CaseVals[i-1].second->getLHS()->getLocStart(), @@ -1046,8 +1060,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If switch has default case, then ignore it. if (!CaseListIsErroneous && !HasConstantCond && ET) { const EnumDecl *ED = ET->getDecl(); - typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> - EnumValsTy; EnumValsTy EnumVals; // Gather all enum values, set their type and sort them, @@ -1058,57 +1070,48 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, EnumVals.push_back(std::make_pair(Val, EDI)); } std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); - EnumValsTy::iterator EIend = + auto EI = EnumVals.begin(), EIEnd = std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); // See which case values aren't in enum. - EnumValsTy::const_iterator EI = EnumVals.begin(); for (CaseValsTy::const_iterator CI = CaseVals.begin(); - CI != CaseVals.end(); CI++) { - while (EI != EIend && EI->first < CI->first) - EI++; - if (EI == EIend || EI->first > CI->first) { - Expr *CaseExpr = CI->second->getLHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; - } + CI != CaseVals.end(); CI++) { + Expr *CaseExpr = CI->second->getLHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, + CI->first)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; } + // See which of case ranges aren't in enum EI = EnumVals.begin(); for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); - RI != CaseRanges.end() && EI != EIend; RI++) { - while (EI != EIend && EI->first < RI->first) - EI++; - - if (EI == EIend || EI->first != RI->first) { - Expr *CaseExpr = RI->second->getLHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; - } + RI != CaseRanges.end(); RI++) { + Expr *CaseExpr = RI->second->getLHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, + RI->first)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; llvm::APSInt Hi = RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); - while (EI != EIend && EI->first < Hi) - EI++; - if (EI == EIend || EI->first != Hi) { - Expr *CaseExpr = RI->second->getRHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; - } + + CaseExpr = RI->second->getRHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, + Hi)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; } // Check which enum vals aren't in switch - CaseValsTy::const_iterator CI = CaseVals.begin(); - CaseRangesTy::const_iterator RI = CaseRanges.begin(); + auto CI = CaseVals.begin(); + auto RI = CaseRanges.begin(); bool hasCasesNotInSwitch = false; SmallVector<DeclarationName,8> UnhandledNames; - for (EI = EnumVals.begin(); EI != EIend; EI++){ + for (EI = EnumVals.begin(); EI != EIEnd; EI++){ // Drop unneeded case values while (CI != CaseVals.end() && CI->first < EI->first) CI++; @@ -1135,29 +1138,15 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default); // Produce a nice diagnostic if multiple values aren't handled. - switch (UnhandledNames.size()) { - case 0: break; - case 1: - Diag(CondExpr->getExprLoc(), TheDefaultStmt - ? diag::warn_def_missing_case1 : diag::warn_missing_case1) - << UnhandledNames[0]; - break; - case 2: - Diag(CondExpr->getExprLoc(), TheDefaultStmt - ? diag::warn_def_missing_case2 : diag::warn_missing_case2) - << UnhandledNames[0] << UnhandledNames[1]; - break; - case 3: - Diag(CondExpr->getExprLoc(), TheDefaultStmt - ? diag::warn_def_missing_case3 : diag::warn_missing_case3) - << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; - break; - default: - Diag(CondExpr->getExprLoc(), TheDefaultStmt - ? diag::warn_def_missing_cases : diag::warn_missing_cases) - << (unsigned)UnhandledNames.size() - << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; - break; + if (!UnhandledNames.empty()) { + DiagnosticBuilder DB = Diag(CondExpr->getExprLoc(), + TheDefaultStmt ? diag::warn_def_missing_case + : diag::warn_missing_case) + << (int)UnhandledNames.size(); + + for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3); + I != E; ++I) + DB << UnhandledNames[I]; } if (!hasCasesNotInSwitch) @@ -1195,30 +1184,37 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context); AdjustAPSInt(RhsVal, DstWidth, DstIsSigned); const EnumDecl *ED = ET->getDecl(); - typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> - EnumValsTy; - EnumValsTy EnumVals; - - // Gather all enum values, set their type and sort them, - // allowing easier comparison with rhs constant. - for (auto *EDI : ED->enumerators()) { - llvm::APSInt Val = EDI->getInitVal(); - AdjustAPSInt(Val, DstWidth, DstIsSigned); - EnumVals.push_back(std::make_pair(Val, EDI)); - } - if (EnumVals.empty()) - return; - std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); - EnumValsTy::iterator EIend = - std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); - - // See which values aren't in the enum. - EnumValsTy::const_iterator EI = EnumVals.begin(); - while (EI != EIend && EI->first < RhsVal) - EI++; - if (EI == EIend || EI->first != RhsVal) { - Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) + + if (ED->hasAttr<FlagEnumAttr>()) { + if (!IsValueInFlagEnum(ED, RhsVal, true)) + Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) << DstType.getUnqualifiedType(); + } else { + typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> + EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, + // allowing easier comparison with rhs constant. + for (auto *EDI : ED->enumerators()) { + llvm::APSInt Val = EDI->getInitVal(); + AdjustAPSInt(Val, DstWidth, DstIsSigned); + EnumVals.push_back(std::make_pair(Val, EDI)); + } + if (EnumVals.empty()) + return; + std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); + EnumValsTy::iterator EIend = + std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + + // See which values aren't in the enum. + EnumValsTy::const_iterator EI = EnumVals.begin(); + while (EI != EIend && EI->first < RhsVal) + EI++; + if (EI == EIend || EI->first != RhsVal) { + Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) + << DstType.getUnqualifiedType(); + } } } } @@ -1832,6 +1828,15 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, /// \return true if an error occurs. static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, SourceLocation Loc, int DiagID) { + if (Decl->getType()->isUndeducedType()) { + ExprResult Res = SemaRef.CorrectDelayedTyposInExpr(Init); + if (!Res.isUsable()) { + Decl->setInvalidDecl(); + return true; + } + Init = Res.get(); + } + // Deduce the type for the iterator variable now rather than leaving it to // AddInitializerToDecl, so we can produce a more suitable diagnostic. QualType InitType; @@ -2368,6 +2373,156 @@ StmtResult Sema::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) { return S; } +// Warn when the loop variable is a const reference that creates a copy. +// Suggest using the non-reference type for copies. If a copy can be prevented +// suggest the const reference type that would do so. +// For instance, given "for (const &Foo : Range)", suggest +// "for (const Foo : Range)" to denote a copy is made for the loop. If +// possible, also suggest "for (const &Bar : Range)" if this type prevents +// the copy altogether. +static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, + const VarDecl *VD, + QualType RangeInitType) { + const Expr *InitExpr = VD->getInit(); + if (!InitExpr) + return; + + QualType VariableType = VD->getType(); + + const MaterializeTemporaryExpr *MTE = + dyn_cast<MaterializeTemporaryExpr>(InitExpr); + + // No copy made. + if (!MTE) + return; + + const Expr *E = MTE->GetTemporaryExpr()->IgnoreImpCasts(); + + // Searching for either UnaryOperator for dereference of a pointer or + // CXXOperatorCallExpr for handling iterators. + while (!isa<CXXOperatorCallExpr>(E) && !isa<UnaryOperator>(E)) { + if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(E)) { + E = CCE->getArg(0); + } else if (const CXXMemberCallExpr *Call = dyn_cast<CXXMemberCallExpr>(E)) { + const MemberExpr *ME = cast<MemberExpr>(Call->getCallee()); + E = ME->getBase(); + } else { + const MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(E); + E = MTE->GetTemporaryExpr(); + } + E = E->IgnoreImpCasts(); + } + + bool ReturnsReference = false; + if (isa<UnaryOperator>(E)) { + ReturnsReference = true; + } else { + const CXXOperatorCallExpr *Call = cast<CXXOperatorCallExpr>(E); + const FunctionDecl *FD = Call->getDirectCallee(); + QualType ReturnType = FD->getReturnType(); + ReturnsReference = ReturnType->isReferenceType(); + } + + if (ReturnsReference) { + // Loop variable creates a temporary. Suggest either to go with + // non-reference loop variable to indiciate a copy is made, or + // the correct time to bind a const reference. + SemaRef.Diag(VD->getLocation(), diag::warn_for_range_const_reference_copy) + << VD << VariableType << E->getType(); + QualType NonReferenceType = VariableType.getNonReferenceType(); + NonReferenceType.removeLocalConst(); + QualType NewReferenceType = + SemaRef.Context.getLValueReferenceType(E->getType().withConst()); + SemaRef.Diag(VD->getLocStart(), diag::note_use_type_or_non_reference) + << NonReferenceType << NewReferenceType << VD->getSourceRange(); + } else { + // The range always returns a copy, so a temporary is always created. + // Suggest removing the reference from the loop variable. + SemaRef.Diag(VD->getLocation(), diag::warn_for_range_variable_always_copy) + << VD << RangeInitType; + QualType NonReferenceType = VariableType.getNonReferenceType(); + NonReferenceType.removeLocalConst(); + SemaRef.Diag(VD->getLocStart(), diag::note_use_non_reference_type) + << NonReferenceType << VD->getSourceRange(); + } +} + +// Warns when the loop variable can be changed to a reference type to +// prevent a copy. For instance, if given "for (const Foo x : Range)" suggest +// "for (const Foo &x : Range)" if this form does not make a copy. +static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef, + const VarDecl *VD) { + const Expr *InitExpr = VD->getInit(); + if (!InitExpr) + return; + + QualType VariableType = VD->getType(); + + if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitExpr)) { + if (!CE->getConstructor()->isCopyConstructor()) + return; + } else if (const CastExpr *CE = dyn_cast<CastExpr>(InitExpr)) { + if (CE->getCastKind() != CK_LValueToRValue) + return; + } else { + return; + } + + // TODO: Determine a maximum size that a POD type can be before a diagnostic + // should be emitted. Also, only ignore POD types with trivial copy + // constructors. + if (VariableType.isPODType(SemaRef.Context)) + return; + + // Suggest changing from a const variable to a const reference variable + // if doing so will prevent a copy. + SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy) + << VD << VariableType << InitExpr->getType(); + SemaRef.Diag(VD->getLocStart(), diag::note_use_reference_type) + << SemaRef.Context.getLValueReferenceType(VariableType) + << VD->getSourceRange(); +} + +/// DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them. +/// 1) for (const foo &x : foos) where foos only returns a copy. Suggest +/// using "const foo x" to show that a copy is made +/// 2) for (const bar &x : foos) where bar is a temporary intialized by bar. +/// Suggest either "const bar x" to keep the copying or "const foo& x" to +/// prevent the copy. +/// 3) for (const foo x : foos) where x is constructed from a reference foo. +/// Suggest "const foo &x" to prevent the copy. +static void DiagnoseForRangeVariableCopies(Sema &SemaRef, + const CXXForRangeStmt *ForStmt) { + if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy, + ForStmt->getLocStart()) && + SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy, + ForStmt->getLocStart()) && + SemaRef.Diags.isIgnored(diag::warn_for_range_copy, + ForStmt->getLocStart())) { + return; + } + + const VarDecl *VD = ForStmt->getLoopVariable(); + if (!VD) + return; + + QualType VariableType = VD->getType(); + + if (VariableType->isIncompleteType()) + return; + + const Expr *InitExpr = VD->getInit(); + if (!InitExpr) + return; + + if (VariableType->isReferenceType()) { + DiagnoseForRangeReferenceVariableCopies(SemaRef, VD, + ForStmt->getRangeInit()->getType()); + } else if (VariableType.isConstQualified()) { + DiagnoseForRangeConstVariableCopies(SemaRef, VD); + } +} + /// 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 @@ -2385,6 +2540,8 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B, diag::warn_empty_range_based_for_body); + DiagnoseForRangeVariableCopies(*this, ForStmt); + return S; } @@ -2423,6 +2580,14 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E); } +static void CheckJumpOutOfSEHFinally(Sema &S, SourceLocation Loc, + const Scope &DestScope) { + if (!S.CurrentSEHFinally.empty() && + DestScope.Contains(*S.CurrentSEHFinally.back())) { + S.Diag(Loc, diag::warn_jump_out_of_seh_finally); + } +} + StmtResult Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { Scope *S = CurScope->getContinueParent(); @@ -2430,6 +2595,7 @@ Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { // C99 6.8.6.2p1: A break shall appear only in or as a loop body. return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop)); } + CheckJumpOutOfSEHFinally(*this, ContinueLoc, *S); return new (Context) ContinueStmt(ContinueLoc); } @@ -2444,6 +2610,7 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { if (S->isOpenMPLoopScope()) return StmtError(Diag(BreakLoc, diag::err_omp_loop_cannot_use_stmt) << "break"); + CheckJumpOutOfSEHFinally(*this, BreakLoc, *S); return new (Context) BreakStmt(BreakLoc); } @@ -2903,6 +3070,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, CurScope->setNoNRVO(); } + CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent()); + return R; } @@ -3179,7 +3348,7 @@ Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; if (!Throw) { - // @throw without an expression designates a rethrow (which much occur + // @throw without an expression designates a rethrow (which must occur // in the context of an @catch clause). Scope *AtCatchParent = CurScope; while (AtCatchParent && !AtCatchParent->isAtCatchScope()) @@ -3251,35 +3420,112 @@ Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) { } namespace { +class CatchHandlerType { + QualType QT; + unsigned IsPointer : 1; -class TypeWithHandler { - QualType t; - CXXCatchStmt *stmt; -public: - TypeWithHandler(const QualType &type, CXXCatchStmt *statement) - : t(type), stmt(statement) {} + // This is a special constructor to be used only with DenseMapInfo's + // getEmptyKey() and getTombstoneKey() functions. + friend struct llvm::DenseMapInfo<CatchHandlerType>; + enum Unique { ForDenseMap }; + CatchHandlerType(QualType QT, Unique) : QT(QT), IsPointer(false) {} - // An arbitrary order is fine as long as it places identical - // types next to each other. - bool operator<(const TypeWithHandler &y) const { - if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr()) - return true; - if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr()) +public: + /// Used when creating a CatchHandlerType from a handler type; will determine + /// whether the type is a pointer or reference and will strip off the the top + /// level pointer and cv-qualifiers. + CatchHandlerType(QualType Q) : QT(Q), IsPointer(false) { + if (QT->isPointerType()) + IsPointer = true; + + if (IsPointer || QT->isReferenceType()) + QT = QT->getPointeeType(); + QT = QT.getUnqualifiedType(); + } + + /// Used when creating a CatchHandlerType from a base class type; pretends the + /// type passed in had the pointer qualifier, does not need to get an + /// unqualified type. + CatchHandlerType(QualType QT, bool IsPointer) + : QT(QT), IsPointer(IsPointer) {} + + QualType underlying() const { return QT; } + bool isPointer() const { return IsPointer; } + + friend bool operator==(const CatchHandlerType &LHS, + const CatchHandlerType &RHS) { + // If the pointer qualification does not match, we can return early. + if (LHS.IsPointer != RHS.IsPointer) return false; - else - return getTypeSpecStartLoc() < y.getTypeSpecStartLoc(); + // Otherwise, check the underlying type without cv-qualifiers. + return LHS.QT == RHS.QT; + } +}; +} // namespace + +namespace llvm { +template <> struct DenseMapInfo<CatchHandlerType> { + static CatchHandlerType getEmptyKey() { + return CatchHandlerType(DenseMapInfo<QualType>::getEmptyKey(), + CatchHandlerType::ForDenseMap); } - bool operator==(const TypeWithHandler& other) const { - return t == other.t; + static CatchHandlerType getTombstoneKey() { + return CatchHandlerType(DenseMapInfo<QualType>::getTombstoneKey(), + CatchHandlerType::ForDenseMap); } - CXXCatchStmt *getCatchStmt() const { return stmt; } - SourceLocation getTypeSpecStartLoc() const { - return stmt->getExceptionDecl()->getTypeSpecStartLoc(); + static unsigned getHashValue(const CatchHandlerType &Base) { + return DenseMapInfo<QualType>::getHashValue(Base.underlying()); } + + static bool isEqual(const CatchHandlerType &LHS, + const CatchHandlerType &RHS) { + return LHS == RHS; + } +}; + +// It's OK to treat CatchHandlerType as a POD type. +template <> struct isPodLike<CatchHandlerType> { + static const bool value = true; }; +} + +namespace { +class CatchTypePublicBases { + ASTContext &Ctx; + const llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> &TypesToCheck; + const bool CheckAgainstPointer; + + CXXCatchStmt *FoundHandler; + CanQualType FoundHandlerType; +public: + CatchTypePublicBases( + ASTContext &Ctx, + const llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> &T, bool C) + : Ctx(Ctx), TypesToCheck(T), CheckAgainstPointer(C), + FoundHandler(nullptr) {} + + CXXCatchStmt *getFoundHandler() const { return FoundHandler; } + CanQualType getFoundHandlerType() const { return FoundHandlerType; } + + static bool FindPublicBasesOfType(const CXXBaseSpecifier *S, CXXBasePath &, + void *User) { + auto &PBOT = *reinterpret_cast<CatchTypePublicBases *>(User); + if (S->getAccessSpecifier() == AccessSpecifier::AS_public) { + CatchHandlerType Check(S->getType(), PBOT.CheckAgainstPointer); + auto M = PBOT.TypesToCheck; + auto I = M.find(Check); + if (I != M.end()) { + PBOT.FoundHandler = I->second; + PBOT.FoundHandlerType = PBOT.Ctx.getCanonicalType(S->getType()); + return true; + } + } + return false; + } +}; } /// ActOnCXXTryBlock - Takes a try compound-statement and a number of @@ -3289,74 +3535,120 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // Don't report an error if 'try' is used in system headers. if (!getLangOpts().CXXExceptions && !getSourceManager().isInSystemHeader(TryLoc)) - Diag(TryLoc, diag::err_exceptions_disabled) << "try"; + Diag(TryLoc, diag::err_exceptions_disabled) << "try"; if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try"; + sema::FunctionScopeInfo *FSI = getCurFunction(); + + // C++ try is incompatible with SEH __try. + if (!getLangOpts().Borland && FSI->FirstSEHTryLoc.isValid()) { + Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); + Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; + } + const unsigned NumHandlers = Handlers.size(); - assert(NumHandlers > 0 && + assert(!Handlers.empty() && "The parser shouldn't call this if there are no handlers."); - SmallVector<TypeWithHandler, 8> TypesWithHandlers; - + llvm::DenseMap<CatchHandlerType, CXXCatchStmt *> HandledTypes; for (unsigned i = 0; i < NumHandlers; ++i) { - CXXCatchStmt *Handler = cast<CXXCatchStmt>(Handlers[i]); - if (!Handler->getExceptionDecl()) { - if (i < NumHandlers - 1) - return StmtError(Diag(Handler->getLocStart(), - diag::err_early_catch_all)); + CXXCatchStmt *H = cast<CXXCatchStmt>(Handlers[i]); + // Diagnose when the handler is a catch-all handler, but it isn't the last + // handler for the try block. [except.handle]p5. Also, skip exception + // declarations that are invalid, since we can't usefully report on them. + if (!H->getExceptionDecl()) { + if (i < NumHandlers - 1) + return StmtError(Diag(H->getLocStart(), diag::err_early_catch_all)); + continue; + } else if (H->getExceptionDecl()->isInvalidDecl()) continue; - } - - const QualType CaughtType = Handler->getCaughtType(); - const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType); - TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler)); - } - - // Detect handlers for the same type as an earlier one. - if (NumHandlers > 1) { - llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end()); - - TypeWithHandler prev = TypesWithHandlers[0]; - for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) { - TypeWithHandler curr = TypesWithHandlers[i]; - if (curr == prev) { - Diag(curr.getTypeSpecStartLoc(), - diag::warn_exception_caught_by_earlier_handler) - << curr.getCatchStmt()->getCaughtType().getAsString(); - Diag(prev.getTypeSpecStartLoc(), - diag::note_previous_exception_handler) - << prev.getCatchStmt()->getCaughtType().getAsString(); + // Walk the type hierarchy to diagnose when this type has already been + // handled (duplication), or cannot be handled (derivation inversion). We + // ignore top-level cv-qualifiers, per [except.handle]p3 + CatchHandlerType HandlerCHT = + (QualType)Context.getCanonicalType(H->getCaughtType()); + + // We can ignore whether the type is a reference or a pointer; we need the + // underlying declaration type in order to get at the underlying record + // decl, if there is one. + QualType Underlying = HandlerCHT.underlying(); + if (auto *RD = Underlying->getAsCXXRecordDecl()) { + if (!RD->hasDefinition()) + continue; + // Check that none of the public, unambiguous base classes are in the + // map ([except.handle]p1). Give the base classes the same pointer + // qualification as the original type we are basing off of. This allows + // comparison against the handler type using the same top-level pointer + // as the original type. + CXXBasePaths Paths; + Paths.setOrigin(RD); + CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer()); + if (RD->lookupInBases(CatchTypePublicBases::FindPublicBasesOfType, &CTPB, + Paths)) { + const CXXCatchStmt *Problem = CTPB.getFoundHandler(); + if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) { + Diag(H->getExceptionDecl()->getTypeSpecStartLoc(), + diag::warn_exception_caught_by_earlier_handler) + << H->getCaughtType(); + Diag(Problem->getExceptionDecl()->getTypeSpecStartLoc(), + diag::note_previous_exception_handler) + << Problem->getCaughtType(); + } } + } - prev = curr; + // Add the type the list of ones we have handled; diagnose if we've already + // handled it. + auto R = HandledTypes.insert(std::make_pair(H->getCaughtType(), H)); + if (!R.second) { + const CXXCatchStmt *Problem = R.first->second; + Diag(H->getExceptionDecl()->getTypeSpecStartLoc(), + diag::warn_exception_caught_by_earlier_handler) + << H->getCaughtType(); + Diag(Problem->getExceptionDecl()->getTypeSpecStartLoc(), + diag::note_previous_exception_handler) + << Problem->getCaughtType(); } } - getCurFunction()->setHasBranchProtectedScope(); - - // FIXME: We should detect handlers that cannot catch anything because an - // earlier handler catches a superclass. Need to find a method that is not - // quadratic for this. - // Neither of these are explicitly forbidden, but every compiler detects them - // and warns. + FSI->setHasCXXTry(TryLoc); return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers); } -StmtResult -Sema::ActOnSEHTryBlock(bool IsCXXTry, - SourceLocation TryLoc, - Stmt *TryBlock, - Stmt *Handler) { +StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, + Stmt *TryBlock, Stmt *Handler) { assert(TryBlock && Handler); - getCurFunction()->setHasBranchProtectedScope(); + sema::FunctionScopeInfo *FSI = getCurFunction(); + + // SEH __try is incompatible with C++ try. Borland appears to support this, + // however. + if (!getLangOpts().Borland) { + if (FSI->FirstCXXTryLoc.isValid()) { + Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); + Diag(FSI->FirstCXXTryLoc, diag::note_conflicting_try_here) << "'try'"; + } + } + + FSI->setHasSEHTry(TryLoc); - return SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler); + // Reject __try in Obj-C methods, blocks, and captured decls, since we don't + // track if they use SEH. + DeclContext *DC = CurContext; + while (DC && !DC->isFunctionOrMethod()) + DC = DC->getParent(); + FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DC); + if (FD) + FD->setUsesSEHTry(true); + else + Diag(TryLoc, diag::err_seh_try_outside_functions); + + return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler); } StmtResult @@ -3374,11 +3666,18 @@ Sema::ActOnSEHExceptBlock(SourceLocation Loc, return SEHExceptStmt::Create(Context,Loc,FilterExpr,Block); } -StmtResult -Sema::ActOnSEHFinallyBlock(SourceLocation Loc, - Stmt *Block) { +void Sema::ActOnStartSEHFinallyBlock() { + CurrentSEHFinally.push_back(CurScope); +} + +void Sema::ActOnAbortSEHFinallyBlock() { + CurrentSEHFinally.pop_back(); +} + +StmtResult Sema::ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block) { assert(Block); - return SEHFinallyStmt::Create(Context,Loc,Block); + CurrentSEHFinally.pop_back(); + return SEHFinallyStmt::Create(Context, Loc, Block); } StmtResult @@ -3388,6 +3687,7 @@ Sema::ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope) { SEHTryParent = SEHTryParent->getParent(); if (!SEHTryParent) return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try)); + CheckJumpOutOfSEHFinally(*this, Loc, *SEHTryParent); return new (Context) SEHLeaveStmt(Loc); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp index 0d32581..9f48616 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/TargetInfo.h" @@ -86,6 +87,11 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) { WorkList.push_back(E); while (WorkList.size()) { Expr *E = WorkList.pop_back_val(); + if (isa<CXXThisExpr>(E)) { + S.Diag(E->getLocStart(), diag::err_asm_naked_this_ref); + S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute); + return true; + } if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (isa<ParmVarDecl>(DRE->getDecl())) { S.Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref); @@ -118,6 +124,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // The parser verifies that there is a string literal here. assert(AsmString->isAscii()); + bool ValidateConstraints = + DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl()); + for (unsigned i = 0; i != NumOutputs; i++) { StringLiteral *Literal = Constraints[i]; assert(Literal->isAscii()); @@ -127,7 +136,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, OutputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); - if (!Context.getTargetInfo().validateOutputConstraint(Info)) + if (ValidateConstraints && + !Context.getTargetInfo().validateOutputConstraint(Info)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_output_constraint) << Info.getConstraintStr()); @@ -201,8 +211,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, InputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); - if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), - NumOutputs, Info)) { + if (ValidateConstraints && + !Context.getTargetInfo().validateInputConstraint( + OutputConstraintInfos.data(), NumOutputs, Info)) { return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_input_constraint) << Info.getConstraintStr()); @@ -307,32 +318,22 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (!Piece.isOperand()) continue; // Look for the correct constraint index. - unsigned Idx = 0; - unsigned ConstraintIdx = 0; - for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) { - TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; - if (Idx == Piece.getOperandNo()) - break; - ++Idx; - - if (Info.isReadWrite()) { - if (Idx == Piece.getOperandNo()) - break; - ++Idx; - } - } + unsigned ConstraintIdx = Piece.getOperandNo(); + unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs(); - for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) { - TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; - if (Idx == Piece.getOperandNo()) - break; - ++Idx; + // Look for the (ConstraintIdx - NumOperands + 1)th constraint with + // modifier '+'. + if (ConstraintIdx >= NumOperands) { + unsigned I = 0, E = NS->getNumOutputs(); - if (Info.isReadWrite()) { - if (Idx == Piece.getOperandNo()) + for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I) + if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) { + ConstraintIdx = I; break; - ++Idx; - } + } + + assert(I != E && "Invalid operand number should have been caught in " + " AnalyzeAsmString"); } // Now that we have the right indexes go ahead and check. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index 1e71762..37eeee2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -836,7 +836,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, AccessSpecifier AS, SourceLocation ModulePrivateLoc, SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, - TemplateParameterList** OuterTemplateParamLists) { + TemplateParameterList** OuterTemplateParamLists, + SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); @@ -993,6 +994,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // Check for redefinition of this class template. if (TUK == TUK_Definition) { if (TagDecl *Def = PrevRecordDecl->getDefinition()) { + // If we have a prior definition that is not visible, treat this as + // simply making that previous definition visible. + NamedDecl *Hidden = nullptr; + if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) { + SkipBody->ShouldSkip = true; + auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate(); + assert(Tmpl && "original definition of a class template is not a " + "class template?"); + makeMergedDefinitionVisible(Hidden, KWLoc); + makeMergedDefinitionVisible(Tmpl, KWLoc); + return Def; + } + Diag(NameLoc, diag::err_redefinition) << Name; Diag(Def->getLocation(), diag::note_previous_definition); // FIXME: Would it make sense to try to "forget" the previous @@ -1296,6 +1310,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for template type parameters. TemplateTypeParmDecl *OldTypeParm = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr; + // FIXME: There might be a visible declaration of this template parameter. + if (OldTypeParm && !LookupResult::isVisible(*this, OldTypeParm)) + OldTypeParm = nullptr; if (NewTypeParm->isParameterPack()) { assert(!NewTypeParm->hasDefaultArgument() && @@ -1341,6 +1358,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for non-type template parameters NonTypeTemplateParmDecl *OldNonTypeParm = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : nullptr; + if (OldNonTypeParm && !LookupResult::isVisible(*this, OldNonTypeParm)) + OldNonTypeParm = nullptr; if (NewNonTypeParm->isParameterPack()) { assert(!NewNonTypeParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); @@ -1388,6 +1407,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for template template parameters TemplateTemplateParmDecl *OldTemplateParm = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : nullptr; + if (OldTemplateParm && !LookupResult::isVisible(*this, OldTemplateParm)) + OldTemplateParm = nullptr; if (NewTemplateParm->isParameterPack()) { assert(!NewTemplateParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); @@ -1798,7 +1819,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( } } else if (const TemplateSpecializationType *TST = T->getAs<TemplateSpecializationType>()) { - if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) { + if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) { ExpectedTemplateParams = Template->getTemplateParameters(); NeedNonemptyTemplateHeader = true; } @@ -5835,11 +5856,13 @@ static bool CheckTemplateSpecializationScope(Sema &S, if (isa<TranslationUnitDecl>(SpecializedContext)) S.Diag(Loc, diag::err_template_spec_redecl_global_scope) << EntityKind << Specialized; - else if (isa<NamespaceDecl>(SpecializedContext)) - S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope) - << EntityKind << Specialized - << cast<NamedDecl>(SpecializedContext); - else + else if (isa<NamespaceDecl>(SpecializedContext)) { + int Diag = diag::err_template_spec_redecl_out_of_scope; + if (S.getLangOpts().MicrosoftExt) + Diag = diag::ext_ms_template_spec_redecl_out_of_scope; + S.Diag(Loc, Diag) << EntityKind << Specialized + << cast<NamedDecl>(SpecializedContext); + } else llvm_unreachable("unexpected namespace context for specialization"); S.Diag(Specialized->getLocation(), diag::note_specialized_entity); @@ -6036,7 +6059,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, AttributeList *Attr, - MultiTemplateParamsArg TemplateParameterLists) { + MultiTemplateParamsArg + TemplateParameterLists, + SkipBodyInfo *SkipBody) { assert(TUK != TUK_Reference && "References are not specializations"); CXXScopeSpec &SS = TemplateId.SS; @@ -6347,7 +6372,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Check that this isn't a redefinition of this specialization. if (TUK == TUK_Definition) { - if (RecordDecl *Def = Specialization->getDefinition()) { + RecordDecl *Def = Specialization->getDefinition(); + NamedDecl *Hidden = nullptr; + if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) { + SkipBody->ShouldSkip = true; + makeMergedDefinitionVisible(Hidden, KWLoc); + // From here on out, treat this as just a redeclaration. + TUK = TUK_Declaration; + } else if (Def) { SourceRange Range(TemplateNameLoc, RAngleLoc); Diag(TemplateNameLoc, diag::err_redefinition) << Context.getTypeDeclType(Specialization) << Range; @@ -7177,9 +7209,27 @@ Sema::ActOnExplicitInstantiation(Scope *S, // There are two forms of explicit instantiation: an explicit instantiation // definition and an explicit instantiation declaration. An explicit // instantiation declaration begins with the extern keyword. [...] - TemplateSpecializationKind TSK - = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition - : TSK_ExplicitInstantiationDeclaration; + TemplateSpecializationKind TSK = ExternLoc.isInvalid() + ? TSK_ExplicitInstantiationDefinition + : TSK_ExplicitInstantiationDeclaration; + + if (TSK == TSK_ExplicitInstantiationDeclaration) { + // Check for dllexport class template instantiation declarations. + for (AttributeList *A = Attr; A; A = A->getNext()) { + if (A->getKind() == AttributeList::AT_DLLExport) { + Diag(ExternLoc, + diag::warn_attribute_dllexport_explicit_instantiation_decl); + Diag(A->getLoc(), diag::note_attribute); + break; + } + } + + if (auto *A = ClassTemplate->getTemplatedDecl()->getAttr<DLLExportAttr>()) { + Diag(ExternLoc, + diag::warn_attribute_dllexport_explicit_instantiation_decl); + Diag(A->getLocation(), diag::note_attribute); + } + } // Translate the parser's template argument list in our AST format. TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); @@ -7315,10 +7365,19 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Fix a TSK_ExplicitInstantiationDeclaration followed by a // TSK_ExplicitInstantiationDefinition if (Old_TSK == TSK_ExplicitInstantiationDeclaration && - TSK == TSK_ExplicitInstantiationDefinition) + TSK == TSK_ExplicitInstantiationDefinition) { // FIXME: Need to notify the ASTMutationListener that we did this. Def->setTemplateSpecializationKind(TSK); + if (!getDLLAttr(Def) && getDLLAttr(Specialization)) { + auto *A = cast<InheritableAttr>( + getDLLAttr(Specialization)->clone(getASTContext())); + A->setInherited(true); + Def->addAttr(A); + checkClassLevelDLLAttribute(Def); + } + } + InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); } @@ -8285,7 +8344,7 @@ void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD, // Take tokens to avoid allocations LPT->Toks.swap(Toks); LPT->D = FnD; - LateParsedTemplateMap[FD] = LPT; + LateParsedTemplateMap.insert(std::make_pair(FD, LPT)); FD->setLateTemplateParsed(true); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index dd2a4d2..6f676ad 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -91,30 +91,6 @@ DeduceTemplateArguments(Sema &S, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced); -/// \brief Whether template argument deduction for two reference parameters -/// resulted in the argument type, parameter type, or neither type being more -/// qualified than the other. -enum DeductionQualifierComparison { - NeitherMoreQualified = 0, - ParamMoreQualified, - ArgMoreQualified -}; - -/// \brief Stores the result of comparing two reference parameters while -/// performing template argument deduction for partial ordering of function -/// templates. -struct RefParamPartialOrderingComparison { - /// \brief Whether the parameter type is an rvalue reference type. - bool ParamIsRvalueRef; - /// \brief Whether the argument type is an rvalue reference type. - bool ArgIsRvalueRef; - - /// \brief Whether the parameter or argument (or neither) is more qualified. - DeductionQualifierComparison Qualifiers; -}; - - - static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(Sema &S, TemplateParameterList *TemplateParams, @@ -124,9 +100,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, SmallVectorImpl<DeducedTemplateArgument> & Deduced, unsigned TDF, - bool PartialOrdering = false, - SmallVectorImpl<RefParamPartialOrderingComparison> * - RefParamComparisons = nullptr); + bool PartialOrdering = false); static Sema::TemplateDeductionResult DeduceTemplateArguments(Sema &S, @@ -602,6 +576,7 @@ struct clang::DeducedPack { DeducedPack *Outer; }; +namespace { /// A scope in which we're performing pack deduction. class PackDeductionScope { public: @@ -756,6 +731,7 @@ private: SmallVector<DeducedPack, 2> Packs; }; +} // namespace /// \brief Deduce the template arguments by comparing the list of parameter /// types to the list of argument types, as in the parameter-type-lists of @@ -784,9 +760,6 @@ private: /// deduction for during partial ordering for a call /// (C++0x [temp.deduct.partial]). /// -/// \param RefParamComparisons If we're performing template argument deduction -/// in the context of partial ordering, the set of qualifier comparisons. -/// /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. @@ -798,9 +771,7 @@ DeduceTemplateArguments(Sema &S, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF, - bool PartialOrdering = false, - SmallVectorImpl<RefParamPartialOrderingComparison> * - RefParamComparisons = nullptr) { + bool PartialOrdering = false) { // Fast-path check to see if we have too many/too few arguments. if (NumParams != NumArgs && !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) && @@ -836,8 +807,7 @@ DeduceTemplateArguments(Sema &S, = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Params[ParamIdx], Args[ArgIdx], Info, Deduced, TDF, - PartialOrdering, - RefParamComparisons)) + PartialOrdering)) return Result; ++ArgIdx; @@ -869,8 +839,7 @@ DeduceTemplateArguments(Sema &S, if (Sema::TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern, Args[ArgIdx], Info, Deduced, - TDF, PartialOrdering, - RefParamComparisons)) + TDF, PartialOrdering)) return Result; PackScope.nextPackElement(); @@ -967,9 +936,6 @@ bool Sema::isSameOrCompatibleFunctionType(CanQualType Param, /// \param PartialOrdering Whether we're performing template argument deduction /// in the context of partial ordering (C++0x [temp.deduct.partial]). /// -/// \param RefParamComparisons If we're performing template argument deduction -/// in the context of partial ordering, the set of qualifier comparisons. -/// /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. @@ -980,9 +946,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF, - bool PartialOrdering, - SmallVectorImpl<RefParamPartialOrderingComparison> * - RefParamComparisons) { + bool PartialOrdering) { // We only want to look at the canonical types, since typedefs and // sugar are not part of template argument deduction. QualType Param = S.Context.getCanonicalType(ParamIn); @@ -995,7 +959,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, Arg = ArgExpansion->getPattern(); if (PartialOrdering) { - // C++0x [temp.deduct.partial]p5: + // C++11 [temp.deduct.partial]p5: // Before the partial ordering is done, certain transformations are // performed on the types used for partial ordering: // - If P is a reference type, P is replaced by the type referred to. @@ -1008,42 +972,42 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, if (ArgRef) Arg = ArgRef->getPointeeType(); - if (RefParamComparisons && ParamRef && ArgRef) { - // C++0x [temp.deduct.partial]p6: - // If both P and A were reference types (before being replaced with the - // type referred to above), determine which of the two types (if any) is - // more cv-qualified than the other; otherwise the types are considered - // to be equally cv-qualified for partial ordering purposes. The result - // of this determination will be used below. + if (ParamRef && ArgRef && S.Context.hasSameUnqualifiedType(Param, Arg)) { + // C++11 [temp.deduct.partial]p9: + // If, for a given type, deduction succeeds in both directions (i.e., + // the types are identical after the transformations above) and both + // P and A were reference types [...]: + // - if [one type] was an lvalue reference and [the other type] was + // not, [the other type] is not considered to be at least as + // specialized as [the first type] + // - if [one type] is more cv-qualified than [the other type], + // [the other type] is not considered to be at least as specialized + // as [the first type] + // Objective-C ARC adds: + // - [one type] has non-trivial lifetime, [the other type] has + // __unsafe_unretained lifetime, and the types are otherwise + // identical // - // We save this information for later, using it only when deduction - // succeeds in both directions. - RefParamPartialOrderingComparison Comparison; - Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>(); - Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>(); - Comparison.Qualifiers = NeitherMoreQualified; - + // A is "considered to be at least as specialized" as P iff deduction + // succeeds, so we model this as a deduction failure. Note that + // [the first type] is P and [the other type] is A here; the standard + // gets this backwards. Qualifiers ParamQuals = Param.getQualifiers(); Qualifiers ArgQuals = Arg.getQualifiers(); - if (ParamQuals.isStrictSupersetOf(ArgQuals)) - Comparison.Qualifiers = ParamMoreQualified; - else if (ArgQuals.isStrictSupersetOf(ParamQuals)) - Comparison.Qualifiers = ArgMoreQualified; - else if (ArgQuals.getObjCLifetime() != ParamQuals.getObjCLifetime() && - ArgQuals.withoutObjCLifetime() - == ParamQuals.withoutObjCLifetime()) { - // Prefer binding to non-__unsafe_autoretained parameters. - if (ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone && - ParamQuals.getObjCLifetime()) - Comparison.Qualifiers = ParamMoreQualified; - else if (ParamQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone && - ArgQuals.getObjCLifetime()) - Comparison.Qualifiers = ArgMoreQualified; + if ((ParamRef->isLValueReferenceType() && + !ArgRef->isLValueReferenceType()) || + ParamQuals.isStrictSupersetOf(ArgQuals) || + (ParamQuals.hasNonTrivialObjCLifetime() && + ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone && + ParamQuals.withoutObjCLifetime() == + ArgQuals.withoutObjCLifetime())) { + Info.FirstArg = TemplateArgument(ParamIn); + Info.SecondArg = TemplateArgument(ArgIn); + return Sema::TDK_NonDeducedMismatch; } - RefParamComparisons->push_back(Comparison); } - // C++0x [temp.deduct.partial]p7: + // C++11 [temp.deduct.partial]p7: // Remove any top-level cv-qualifiers: // - If P is a cv-qualified type, P is replaced by the cv-unqualified // version of P. @@ -2784,7 +2748,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs) { + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs, + bool PartialOverloading) { TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); @@ -2911,6 +2876,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, const_cast<NamedDecl *>(TemplateParams->getParam(I))); Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size())); + if (PartialOverloading) break; + return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete; } @@ -3136,34 +3103,16 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, // are ignored for type deduction. if (ParamType.hasQualifiers()) ParamType = ParamType.getUnqualifiedType(); - const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>(); - if (ParamRefType) { - QualType PointeeType = ParamRefType->getPointeeType(); - // If the argument has incomplete array type, try to complete its type. - if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0)) - ArgType = Arg->getType(); - - // [C++0x] If P is an rvalue reference to a cv-unqualified - // template parameter and the argument is an lvalue, the type - // "lvalue reference to A" is used in place of A for type - // deduction. - if (isa<RValueReferenceType>(ParamType)) { - if (!PointeeType.getQualifiers() && - isa<TemplateTypeParmType>(PointeeType) && - Arg->Classify(S.Context).isLValue() && - Arg->getType() != S.Context.OverloadTy && - Arg->getType() != S.Context.BoundMemberTy) - ArgType = S.Context.getLValueReferenceType(ArgType); - } - - // [...] If P is a reference type, the type referred to by P is used - // for type deduction. - ParamType = PointeeType; - } + // [...] If P is a reference type, the type referred to by P is + // used for type deduction. + const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>(); + if (ParamRefType) + ParamType = ParamRefType->getPointeeType(); - // Overload sets usually make this parameter an undeduced - // context, but there are sometimes special circumstances. + // Overload sets usually make this parameter an undeduced context, + // but there are sometimes special circumstances. Typically + // involving a template-id-expr. if (ArgType == S.Context.OverloadTy) { ArgType = ResolveOverloadForDeduction(S, TemplateParams, Arg, ParamType, @@ -3173,12 +3122,17 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, } if (ParamRefType) { + // If the argument has incomplete array type, try to complete its type. + if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0)) + ArgType = Arg->getType(); + // C++0x [temp.deduct.call]p3: - // [...] If P is of the form T&&, where T is a template parameter, and - // the argument is an lvalue, the type A& is used in place of A for - // type deduction. + // If P is an rvalue reference to a cv-unqualified template + // parameter and the argument is an lvalue, the type "lvalue + // reference to A" is used in place of A for type deduction. if (ParamRefType->isRValueReferenceType() && - ParamRefType->getAs<TemplateTypeParmType>() && + !ParamType.getQualifiers() && + isa<TemplateTypeParmType>(ParamType) && Arg->isLValue()) ArgType = S.Context.getLValueReferenceType(ArgType); } else { @@ -3298,26 +3252,28 @@ DeduceTemplateArgumentByListElement(Sema &S, Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, - FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { + FunctionDecl *&Specialization, TemplateDeductionInfo &Info, + bool PartialOverloading) { if (FunctionTemplate->isInvalidDecl()) return TDK_Invalid; FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); + unsigned NumParams = Function->getNumParams(); // C++ [temp.deduct.call]p1: // Template argument deduction is done by comparing each function template // parameter type (call it P) with the type of the corresponding argument // of the call (call it A) as described below. unsigned CheckArgs = Args.size(); - if (Args.size() < Function->getMinRequiredArguments()) + if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading) return TDK_TooFewArguments; - else if (Args.size() > Function->getNumParams()) { + else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) { const FunctionProtoType *Proto = Function->getType()->getAs<FunctionProtoType>(); if (Proto->isTemplateVariadic()) /* Do nothing */; else if (Proto->isVariadic()) - CheckArgs = Function->getNumParams(); + CheckArgs = NumParams; else return TDK_TooManyArguments; } @@ -3344,7 +3300,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( NumExplicitlySpecified = Deduced.size(); } else { // Just fill in the parameter types from the function declaration. - for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) + for (unsigned I = 0; I != NumParams; ++I) ParamTypes.push_back(Function->getParamDecl(I)->getType()); } @@ -3352,8 +3308,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( Deduced.resize(TemplateParams->size()); unsigned ArgIdx = 0; SmallVector<OriginalCallArg, 4> OriginalCallArgs; - for (unsigned ParamIdx = 0, NumParams = ParamTypes.size(); - ParamIdx != NumParams; ++ParamIdx) { + for (unsigned ParamIdx = 0, NumParamTypes = ParamTypes.size(); + ParamIdx != NumParamTypes; ++ParamIdx) { QualType OrigParamType = ParamTypes[ParamIdx]; QualType ParamType = OrigParamType; @@ -3422,7 +3378,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // the function parameter pack. For a function parameter pack that does // not occur at the end of the parameter-declaration-list, the type of // the parameter pack is a non-deduced context. - if (ParamIdx + 1 < NumParams) + if (ParamIdx + 1 < NumParamTypes) break; QualType ParamPattern = ParamExpansion->getPattern(); @@ -3492,7 +3448,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, - Info, &OriginalCallArgs); + Info, &OriginalCallArgs, + PartialOverloading); } QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, @@ -3699,8 +3656,10 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker( FunctionTemplateDecl *InvokerTemplate = LambdaClass-> getLambdaStaticInvoker()->getDescribedFunctionTemplate(); - Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result - = S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0, +#ifndef NDEBUG + Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result = +#endif + S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0, InvokerSpecialized, TDInfo); assert(Result == Sema::TDK_Success && "If the call operator succeeded so should the invoker!"); @@ -4153,8 +4112,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, TemplatePartialOrderingContext TPOC, - unsigned NumCallArguments1, - SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) { + unsigned NumCallArguments1) { FunctionDecl *FD1 = FT1->getTemplatedDecl(); FunctionDecl *FD2 = FT2->getTemplatedDecl(); const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>(); @@ -4219,8 +4177,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, Args2.resize(NumComparedArguments); if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(), Args1.data(), Args1.size(), Info, Deduced, - TDF_None, /*PartialOrdering=*/true, - RefParamComparisons)) + TDF_None, /*PartialOrdering=*/true)) return false; break; @@ -4232,7 +4189,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, if (DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, Proto2->getReturnType(), Proto1->getReturnType(), Info, Deduced, TDF_None, - /*PartialOrdering=*/true, RefParamComparisons)) + /*PartialOrdering=*/true)) return false; break; @@ -4242,8 +4199,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - RefParamComparisons)) + /*PartialOrdering=*/true)) return false; break; } @@ -4342,83 +4298,17 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1, unsigned NumCallArguments2) { - SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons; bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, - NumCallArguments1, nullptr); + NumCallArguments1); bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, - NumCallArguments2, - &RefParamComparisons); + NumCallArguments2); if (Better1 != Better2) // We have a clear winner - return Better1? FT1 : FT2; + return Better1 ? FT1 : FT2; if (!Better1 && !Better2) // Neither is better than the other return nullptr; - // C++0x [temp.deduct.partial]p10: - // If for each type being considered a given template is at least as - // specialized for all types and more specialized for some set of types and - // the other template is not more specialized for any types or is not at - // least as specialized for any types, then the given template is more - // specialized than the other template. Otherwise, neither template is more - // specialized than the other. - Better1 = false; - Better2 = false; - for (unsigned I = 0, N = RefParamComparisons.size(); I != N; ++I) { - // C++0x [temp.deduct.partial]p9: - // If, for a given type, deduction succeeds in both directions (i.e., the - // types are identical after the transformations above) and both P and A - // were reference types (before being replaced with the type referred to - // above): - - // -- if the type from the argument template was an lvalue reference - // and the type from the parameter template was not, the argument - // type is considered to be more specialized than the other; - // otherwise, - if (!RefParamComparisons[I].ArgIsRvalueRef && - RefParamComparisons[I].ParamIsRvalueRef) { - Better2 = true; - if (Better1) - return nullptr; - continue; - } else if (!RefParamComparisons[I].ParamIsRvalueRef && - RefParamComparisons[I].ArgIsRvalueRef) { - Better1 = true; - if (Better2) - return nullptr; - continue; - } - - // -- if the type from the argument template is more cv-qualified than - // the type from the parameter template (as described above), the - // argument type is considered to be more specialized than the - // other; otherwise, - switch (RefParamComparisons[I].Qualifiers) { - case NeitherMoreQualified: - break; - - case ParamMoreQualified: - Better1 = true; - if (Better2) - return nullptr; - continue; - - case ArgMoreQualified: - Better2 = true; - if (Better1) - return nullptr; - continue; - } - - // -- neither type is more specialized than the other. - } - - assert(!(Better1 && Better2) && "Should have broken out in the loop above"); - if (Better1) - return FT1; - else if (Better2) - return FT2; - // FIXME: This mimics what GCC implements, but doesn't match up with the // proposed resolution for core issue 692. This area needs to be sorted out, // but for now we attempt to maintain compatibility. @@ -4591,8 +4481,7 @@ Sema::getMoreSpecializedPartialSpecialization( bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - /*RefParamComparisons=*/nullptr); + /*PartialOrdering=*/true); if (Better1) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end()); InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info); @@ -4605,8 +4494,7 @@ Sema::getMoreSpecializedPartialSpecialization( Deduced.resize(PS1->getTemplateParameters()->size()); bool Better2 = !DeduceTemplateArgumentsByTypeMatch( *this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - /*RefParamComparisons=*/nullptr); + /*PartialOrdering=*/true); if (Better2) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end()); @@ -4649,8 +4537,7 @@ Sema::getMoreSpecializedPartialSpecialization( Deduced.resize(PS2->getTemplateParameters()->size()); bool Better1 = !DeduceTemplateArgumentsByTypeMatch( *this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - /*RefParamComparisons=*/nullptr); + /*PartialOrdering=*/true); if (Better1) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end()); @@ -4666,8 +4553,7 @@ Sema::getMoreSpecializedPartialSpecialization( bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - /*RefParamComparisons=*/nullptr); + /*PartialOrdering=*/true); if (Better2) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end()); InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index 6ac7175..82ff7c0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -200,13 +200,19 @@ bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const { llvm_unreachable("Invalid InstantiationKind!"); } -void Sema::InstantiatingTemplate::Initialize( - ActiveTemplateInstantiation::InstantiationKind Kind, +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, ActiveTemplateInstantiation::InstantiationKind Kind, SourceLocation PointOfInstantiation, SourceRange InstantiationRange, Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, - sema::TemplateDeductionInfo *DeductionInfo) { - SavedInNonInstantiationSFINAEContext = - SemaRef.InNonInstantiationSFINAEContext; + sema::TemplateDeductionInfo *DeductionInfo) + : SemaRef(SemaRef), SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) { + // Don't allow further instantiation if a fatal error has occcured. Any + // diagnostics we might have raised will not be visible. + if (SemaRef.Diags.hasFatalErrorOccurred()) { + Invalid = true; + return; + } Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); if (!Invalid) { ActiveTemplateInstantiation Inst; @@ -225,124 +231,98 @@ void Sema::InstantiatingTemplate::Initialize( } } -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - Decl *Entity, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::TemplateInstantiation, - PointOfInstantiation, InstantiationRange, Entity); -} - -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - FunctionDecl *Entity, ExceptionSpecification, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::ExceptionSpecInstantiation, - PointOfInstantiation, InstantiationRange, Entity); -} - -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - TemplateDecl *Template, - ArrayRef<TemplateArgument> TemplateArgs, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation, - PointOfInstantiation, InstantiationRange, - Template, nullptr, TemplateArgs); -} - -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - FunctionTemplateDecl *FunctionTemplate, - ArrayRef<TemplateArgument> TemplateArgs, - ActiveTemplateInstantiation::InstantiationKind Kind, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(Kind, PointOfInstantiation, InstantiationRange, - FunctionTemplate, nullptr, TemplateArgs, &DeductionInfo); -} - -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - ClassTemplatePartialSpecializationDecl *PartialSpec, - ArrayRef<TemplateArgument> TemplateArgs, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution, - PointOfInstantiation, InstantiationRange, - PartialSpec, nullptr, TemplateArgs, &DeductionInfo); -} +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity, + SourceRange InstantiationRange) + : InstantiatingTemplate(SemaRef, + ActiveTemplateInstantiation::TemplateInstantiation, + PointOfInstantiation, InstantiationRange, Entity) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionDecl *Entity, + ExceptionSpecification, SourceRange InstantiationRange) + : InstantiatingTemplate( + SemaRef, ActiveTemplateInstantiation::ExceptionSpecInstantiation, + PointOfInstantiation, InstantiationRange, Entity) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template, + ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange) + : InstantiatingTemplate( + SemaRef, + ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation, + PointOfInstantiation, InstantiationRange, Template, nullptr, + TemplateArgs) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, + FunctionTemplateDecl *FunctionTemplate, + ArrayRef<TemplateArgument> TemplateArgs, + ActiveTemplateInstantiation::InstantiationKind Kind, + sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) + : InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation, + InstantiationRange, FunctionTemplate, nullptr, + TemplateArgs, &DeductionInfo) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, + ClassTemplatePartialSpecializationDecl *PartialSpec, + ArrayRef<TemplateArgument> TemplateArgs, + sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) + : InstantiatingTemplate( + SemaRef, + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution, + PointOfInstantiation, InstantiationRange, PartialSpec, nullptr, + TemplateArgs, &DeductionInfo) {} Sema::InstantiatingTemplate::InstantiatingTemplate( Sema &SemaRef, SourceLocation PointOfInstantiation, VarTemplatePartialSpecializationDecl *PartialSpec, ArrayRef<TemplateArgument> TemplateArgs, sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution, - PointOfInstantiation, InstantiationRange, - PartialSpec, nullptr, TemplateArgs, &DeductionInfo); -} - -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - ParmVarDecl *Param, - ArrayRef<TemplateArgument> TemplateArgs, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation, - PointOfInstantiation, InstantiationRange, - Param, nullptr, TemplateArgs); -} - - -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - NamedDecl *Template, NonTypeTemplateParmDecl *Param, - ArrayRef<TemplateArgument> TemplateArgs, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution, - PointOfInstantiation, InstantiationRange, - Param, Template, TemplateArgs); -} - -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - NamedDecl *Template, TemplateTemplateParmDecl *Param, - ArrayRef<TemplateArgument> TemplateArgs, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution, - PointOfInstantiation, InstantiationRange, - Param, Template, TemplateArgs); -} - -Sema::InstantiatingTemplate:: -InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - TemplateDecl *Template, NamedDecl *Param, - ArrayRef<TemplateArgument> TemplateArgs, - SourceRange InstantiationRange) - : SemaRef(SemaRef) -{ - Initialize(ActiveTemplateInstantiation::DefaultTemplateArgumentChecking, - PointOfInstantiation, InstantiationRange, - Param, Template, TemplateArgs); -} + : InstantiatingTemplate( + SemaRef, + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution, + PointOfInstantiation, InstantiationRange, PartialSpec, nullptr, + TemplateArgs, &DeductionInfo) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param, + ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange) + : InstantiatingTemplate( + SemaRef, + ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation, + PointOfInstantiation, InstantiationRange, Param, nullptr, + TemplateArgs) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template, + NonTypeTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs, + SourceRange InstantiationRange) + : InstantiatingTemplate( + SemaRef, + ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution, + PointOfInstantiation, InstantiationRange, Param, Template, + TemplateArgs) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template, + TemplateTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs, + SourceRange InstantiationRange) + : InstantiatingTemplate( + SemaRef, + ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution, + PointOfInstantiation, InstantiationRange, Param, Template, + TemplateArgs) {} + +Sema::InstantiatingTemplate::InstantiatingTemplate( + Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template, + NamedDecl *Param, ArrayRef<TemplateArgument> TemplateArgs, + SourceRange InstantiationRange) + : InstantiatingTemplate( + SemaRef, ActiveTemplateInstantiation::DefaultTemplateArgumentChecking, + PointOfInstantiation, InstantiationRange, Param, Template, + TemplateArgs) {} void Sema::InstantiatingTemplate::Clear() { if (!Invalid) { @@ -734,6 +714,20 @@ namespace { } void transformedLocalDecl(Decl *Old, Decl *New) { + // If we've instantiated the call operator of a lambda or the call + // operator template of a generic lambda, update the "instantiation of" + // information. + auto *NewMD = dyn_cast<CXXMethodDecl>(New); + if (NewMD && isLambdaCallOperator(NewMD)) { + auto *OldMD = dyn_cast<CXXMethodDecl>(Old); + if (auto *NewTD = NewMD->getDescribedFunctionTemplate()) + NewTD->setInstantiatedFromMemberTemplate( + OldMD->getDescribedFunctionTemplate()); + else + NewMD->setInstantiationOfMemberFunction(OldMD, + TSK_ImplicitInstantiation); + } + SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New); } @@ -836,28 +830,6 @@ namespace { return TreeTransform<TemplateInstantiator>::TransformLambdaExpr(E); } - ExprResult TransformLambdaScope(LambdaExpr *E, - CXXMethodDecl *NewCallOperator, - ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) { - CXXMethodDecl *const OldCallOperator = E->getCallOperator(); - // In the generic lambda case, we set the NewTemplate to be considered - // an "instantiation" of the OldTemplate. - if (FunctionTemplateDecl *const NewCallOperatorTemplate = - NewCallOperator->getDescribedFunctionTemplate()) { - - FunctionTemplateDecl *const OldCallOperatorTemplate = - OldCallOperator->getDescribedFunctionTemplate(); - NewCallOperatorTemplate->setInstantiatedFromMemberTemplate( - OldCallOperatorTemplate); - } else - // For a non-generic lambda we set the NewCallOperator to - // be an instantiation of the OldCallOperator. - NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator, - TSK_ImplicitInstantiation); - - return inherited::TransformLambdaScope(E, NewCallOperator, - InitCaptureExprsAndTypes); - } TemplateParameterList *TransformTemplateParameterList( TemplateParameterList *OrigTPL) { if (!OrigTPL || !OrigTPL->size()) return OrigTPL; @@ -1767,7 +1739,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, const MultiLevelTemplateArgumentList &TemplateArgs) { bool Invalid = false; SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases; - for (const auto Base : Pattern->bases()) { + for (const auto &Base : Pattern->bases()) { if (!Base.getType()->isDependentType()) { if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) { if (RD->isInvalidDecl()) @@ -2063,6 +2035,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, SourceLocation(), SourceLocation(), nullptr); CheckCompletedCXXClass(Instantiation); + // Default arguments are parsed, if not instantiated. We can go instantiate + // default arg exprs for default constructors if necessary now. + ActOnFinishCXXMemberDefaultArgs(Instantiation); + // Instantiate late parsed attributes, and attach them to their decls. // See Sema::InstantiateAttrs for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(), @@ -2257,7 +2233,7 @@ bool Sema::InstantiateInClassInitializer( EnterExpressionEvaluationContext EvalContext(*this, Sema::PotentiallyEvaluated); - LocalInstantiationScope Scope(*this); + LocalInstantiationScope Scope(*this, true); // Instantiate the initializer. ActOnStartCXXInClassMemberInitializer(); @@ -2812,6 +2788,16 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) { isa<TemplateTemplateParmDecl>(D)) return nullptr; + // Local types referenced prior to definition may require instantiation. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) + if (RD->isLocalClass()) + return nullptr; + + // Enumeration types referenced prior to definition may appear as a result of + // error recovery. + if (isa<EnumDecl>(D)) + return nullptr; + // If we didn't find the decl, then we either have a sema bug, or we have a // forward reference to a label declaration. Return null to indicate that // we have an uninstantiated label. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 40e8617..5c994f8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -202,6 +202,31 @@ static void instantiateDependentEnableIfAttr( New->addAttr(EIA); } +// Constructs and adds to New a new instance of CUDALaunchBoundsAttr using +// template A as the base and arguments from TemplateArgs. +static void instantiateDependentCUDALaunchBoundsAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const CUDALaunchBoundsAttr &Attr, Decl *New) { + // The alignment expression is a constant expression. + EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated); + + ExprResult Result = S.SubstExpr(Attr.getMaxThreads(), TemplateArgs); + if (Result.isInvalid()) + return; + Expr *MaxThreads = Result.getAs<Expr>(); + + Expr *MinBlocks = nullptr; + if (Attr.getMinBlocks()) { + Result = S.SubstExpr(Attr.getMinBlocks(), TemplateArgs); + if (Result.isInvalid()) + return; + MinBlocks = Result.getAs<Expr>(); + } + + S.AddLaunchBoundsAttr(Attr.getLocation(), New, MaxThreads, MinBlocks, + Attr.getSpellingListIndex()); +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -233,6 +258,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } + if (const CUDALaunchBoundsAttr *CUDALaunchBounds = + dyn_cast<CUDALaunchBoundsAttr>(TmplAttr)) { + instantiateDependentCUDALaunchBoundsAttr(*this, TemplateArgs, + *CUDALaunchBounds, New); + continue; + } + // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { @@ -289,6 +321,11 @@ TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { } Decl * +TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) { + llvm_unreachable("extern \"C\" context cannot be instantiated"); +} + +Decl * TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier()); @@ -1265,11 +1302,19 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { // DR1484 clarifies that the members of a local class are instantiated as part // of the instantiation of their enclosing entity. if (D->isCompleteDefinition() && D->isLocalClass()) { + Sema::SavePendingLocalImplicitInstantiationsRAII + SavedPendingLocalImplicitInstantiations(SemaRef); + SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs, TSK_ImplicitInstantiation, /*Complain=*/true); + SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs, TSK_ImplicitInstantiation); + + // This class may have local implicit instantiations that need to be + // performed within this scope. + SemaRef.PerformPendingInstantiations(/*LocalOnly=*/true); } SemaRef.DiagnoseUnusedNestedTypedefs(Record); @@ -3313,12 +3358,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // it marks vtables used in late parsed templates as used. SavePendingLocalImplicitInstantiationsRAII SavedPendingLocalImplicitInstantiations(*this); - std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII> - SavePendingInstantiationsAndVTableUses; - if (Recursive) { - SavePendingInstantiationsAndVTableUses.reset( - new SavePendingInstantiationsAndVTableUsesRAII(*this)); - } + SavePendingInstantiationsAndVTableUsesRAII + SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive); // Call the LateTemplateParser callback if there is a need to late parse // a templated function definition. @@ -3463,8 +3504,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // instantiation of this template. PerformPendingInstantiations(); - // Restore PendingInstantiations and VTableUses. - SavePendingInstantiationsAndVTableUses.reset(); + // PendingInstantiations and VTableUses are restored through + // SavePendingInstantiationsAndVTableUses's destructor. } } @@ -3780,12 +3821,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate // later, while we're still within our own instantiation context. - std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII> - SavePendingInstantiationsAndVTableUses; - if (Recursive) { - SavePendingInstantiationsAndVTableUses.reset( - new SavePendingInstantiationsAndVTableUsesRAII(*this)); - } + SavePendingInstantiationsAndVTableUsesRAII + SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive); LocalInstantiationScope Local(*this); @@ -3812,8 +3849,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // instantiation of this template. PerformPendingInstantiations(); - // Restore PendingInstantiations and VTableUses. - SavePendingInstantiationsAndVTableUses.reset(); + // PendingInstantiations and VTableUses are restored through + // SavePendingInstantiationsAndVTableUses's destructor. } } @@ -3899,12 +3936,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // while we're still within our own instantiation context. SavePendingLocalImplicitInstantiationsRAII SavedPendingLocalImplicitInstantiations(*this); - std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII> - SavePendingInstantiationsAndVTableUses; - if (Recursive) { - SavePendingInstantiationsAndVTableUses.reset( - new SavePendingInstantiationsAndVTableUsesRAII(*this)); - } + SavePendingInstantiationsAndVTableUsesRAII + SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive); // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. @@ -3970,8 +4003,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // instantiation of this template. PerformPendingInstantiations(); - // Restore PendingInstantiations and VTableUses. - SavePendingInstantiationsAndVTableUses.reset(); + // PendingInstantiations and VTableUses are restored through + // SavePendingInstantiationsAndVTableUses's destructor. } } @@ -4409,6 +4442,30 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, if (D->isInvalidDecl()) return nullptr; + // Normally this function only searches for already instantiated declaration + // however we have to make an exclusion for local types used before + // definition as in the code: + // + // template<typename T> void f1() { + // void g1(struct x1); + // struct x1 {}; + // } + // + // In this case instantiation of the type of 'g1' requires definition of + // 'x1', which is defined later. Error recovery may produce an enum used + // before definition. In these cases we need to instantiate relevant + // declarations here. + bool NeedInstantiate = false; + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) + NeedInstantiate = RD->isLocalClass(); + else + NeedInstantiate = isa<EnumDecl>(D); + if (NeedInstantiate) { + Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); + CurrentInstantiationScope->InstantiatedLocal(D, Inst); + return cast<TypeDecl>(Inst); + } + // If we didn't find the decl, then we must have a label decl that hasn't // been found yet. Lazily instantiate it and return it now. assert(isa<LabelDecl>(D)); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp index e4fab71..fd3ba35 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -251,15 +251,10 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, Locations.push_back(Unexpanded[I].second); } - DiagnosticBuilder DB - = Names.size() == 0? Diag(Loc, diag::err_unexpanded_parameter_pack_0) - << (int)UPPC - : Names.size() == 1? Diag(Loc, diag::err_unexpanded_parameter_pack_1) - << (int)UPPC << Names[0] - : Names.size() == 2? Diag(Loc, diag::err_unexpanded_parameter_pack_2) - << (int)UPPC << Names[0] << Names[1] - : Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more) - << (int)UPPC << Names[0] << Names[1]; + DiagnosticBuilder DB = Diag(Loc, diag::err_unexpanded_parameter_pack) + << (int)UPPC << (int)Names.size(); + for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I) + DB << Names[I]; for (unsigned I = 0, N = Locations.size(); I != N; ++I) DB << SourceRange(Locations[I]); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index 0f96a1c..57a4689 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -112,7 +112,6 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_SysVABI: \ case AttributeList::AT_Regparm: \ case AttributeList::AT_Pcs: \ - case AttributeList::AT_PnaclCall: \ case AttributeList::AT_IntelOclBicc // Microsoft-specific type qualifiers. @@ -689,6 +688,31 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, state.setCurrentChunkIndex(declarator.getNumTypeObjects()); } +static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS, + unsigned &TypeQuals, + QualType TypeSoFar, + unsigned RemoveTQs, + unsigned DiagID) { + // If this occurs outside a template instantiation, warn the user about + // it; they probably didn't mean to specify a redundant qualifier. + typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc; + for (QualLoc Qual : {QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()), + QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()), + QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())}) { + if (!(RemoveTQs & Qual.first)) + continue; + + if (S.ActiveTemplateInstantiations.empty()) { + if (TypeQuals & Qual.first) + S.Diag(Qual.second, DiagID) + << DeclSpec::getSpecifierName(Qual.first) << TypeSoFar + << FixItHint::CreateRemoval(Qual.second); + } + + TypeQuals &= ~Qual.first; + } +} + /// \brief Convert the specified declspec to the appropriate type /// object. /// \param state Specifies the declarator containing the declaration specifier @@ -869,8 +893,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { else Result = Context.DoubleTy; - if (S.getLangOpts().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) { - S.Diag(DS.getTypeSpecTypeLoc(), diag::err_double_requires_fp64); + if (S.getLangOpts().OpenCL && + !((S.getLangOpts().OpenCLVersion >= 120) || + S.getOpenCLOptions().cl_khr_fp64)) { + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) + << Result << "cl_khr_fp64"; declarator.setInvalidType(true); } break; @@ -946,6 +973,30 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { << DS.getSourceRange(); declarator.setInvalidType(true); } + } else if (S.getLangOpts().OpenCL) { + if (const AtomicType *AT = Result->getAs<AtomicType>()) { + const BuiltinType *BT = AT->getValueType()->getAs<BuiltinType>(); + bool NoExtTypes = BT && (BT->getKind() == BuiltinType::Int || + BT->getKind() == BuiltinType::UInt || + BT->getKind() == BuiltinType::Float); + if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) { + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) + << Result << "cl_khr_int64_base_atomics"; + declarator.setInvalidType(true); + } + if (!S.getOpenCLOptions().cl_khr_int64_extended_atomics && + !NoExtTypes) { + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) + << Result << "cl_khr_int64_extended_atomics"; + declarator.setInvalidType(true); + } + if (!S.getOpenCLOptions().cl_khr_fp64 && BT && + BT->getKind() == BuiltinType::Double) { + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) + << Result << "cl_khr_fp64"; + declarator.setInvalidType(true); + } + } } // TypeQuals handled by caller. @@ -1091,24 +1142,22 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { - - // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification - // of a function type includes any type qualifiers, the behavior is - // undefined." - if (Result->isFunctionType() && TypeQuals) { - if (TypeQuals & DeclSpec::TQ_const) - S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers) - << Result << DS.getSourceRange(); - else if (TypeQuals & DeclSpec::TQ_volatile) - S.Diag(DS.getVolatileSpecLoc(), - diag::warn_typecheck_function_qualifiers) - << Result << DS.getSourceRange(); - else { - assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) && - "Has CVRA quals but not C, V, R, or A?"); - // No diagnostic; we'll diagnose 'restrict' or '_Atomic' applied to a - // function type later, in BuildQualifiedType. - } + // Warn about CV qualifiers on function types. + // C99 6.7.3p8: + // If the specification of a function type includes any type qualifiers, + // the behavior is undefined. + // C++11 [dcl.fct]p7: + // The effect of a cv-qualifier-seq in a function declarator is not the + // same as adding cv-qualification on top of the function type. In the + // latter case, the cv-qualifiers are ignored. + if (TypeQuals && Result->isFunctionType()) { + diagnoseAndRemoveTypeQualifiers( + S, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile, + S.getLangOpts().CPlusPlus + ? diag::warn_typecheck_function_qualifiers_ignored + : diag::warn_typecheck_function_qualifiers_unspecified); + // No diagnostic for 'restrict' or '_Atomic' applied to a + // function type; we'll diagnose those later, in BuildQualifiedType. } // C++11 [dcl.ref]p1: @@ -1119,25 +1168,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // There don't appear to be any other contexts in which a cv-qualified // reference type could be formed, so the 'ill-formed' clause here appears // to never happen. - if (DS.getTypeSpecType() == DeclSpec::TST_typename && - TypeQuals && Result->isReferenceType()) { - // If this occurs outside a template instantiation, warn the user about - // it; they probably didn't mean to specify a redundant qualifier. - typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc; - QualLoc Quals[] = { - QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()), - QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()), - QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc()) - }; - for (unsigned I = 0, N = llvm::array_lengthof(Quals); I != N; ++I) { - if (S.ActiveTemplateInstantiations.empty()) { - if (TypeQuals & Quals[I].first) - S.Diag(Quals[I].second, diag::warn_typecheck_reference_qualifiers) - << DeclSpec::getSpecifierName(Quals[I].first) << Result - << FixItHint::CreateRemoval(Quals[I].second); - } - TypeQuals &= ~Quals[I].first; - } + if (TypeQuals && Result->isReferenceType()) { + diagnoseAndRemoveTypeQualifiers( + S, DS, TypeQuals, Result, + DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic, + diag::warn_typecheck_reference_qualifiers); } // C90 6.5.3 constraints: "The same type qualifier shall not appear more @@ -1809,13 +1844,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, // exception specification. if (CheckDistantExceptionSpec(T)) { Diag(Loc, diag::err_distant_exception_spec); - - // FIXME: If we're doing this as part of template instantiation, - // we should return immediately. - - // Build the type anyway, but use the canonical type so that the - // exception specifiers are stripped off. - T = Context.getCanonicalType(T); + return QualType(); } // C++ 8.3.3p3: A pointer to member shall not point to ... a member @@ -2463,6 +2492,10 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, // in a member pointer. IsCXXInstanceMethod = D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer; + } else if (D.getContext() == Declarator::LambdaExprContext) { + // This can only be a call operator for a lambda, which is an instance + // method. + IsCXXInstanceMethod = true; } else { // We're the innermost decl chunk, so must be a function declarator. assert(D.isFunctionDeclarator()); @@ -2476,8 +2509,24 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, } } - return S.Context.getDefaultCallingConvention(FTI.isVariadic, - IsCXXInstanceMethod); + CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic, + IsCXXInstanceMethod); + + // Attribute AT_OpenCLKernel affects the calling convention only on + // the SPIR target, hence it cannot be treated as a calling + // convention attribute. This is the simplest place to infer + // "spir_kernel" for OpenCL kernels on SPIR. + if (CC == CC_SpirFunction) { + for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); + Attr; Attr = Attr->getNext()) { + if (Attr->getKind() == AttributeList::AT_OpenCLKernel) { + CC = CC_SpirKernel; + break; + } + } + } + + return CC; } static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, @@ -2792,8 +2841,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // class type in C++. if ((T.getCVRQualifiers() || T->isAtomicType()) && !(S.getLangOpts().CPlusPlus && - (T->isDependentType() || T->isRecordType()))) - diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex); + (T->isDependentType() || T->isRecordType()))) { + if (T->isVoidType() && !S.getLangOpts().CPlusPlus && + D.getFunctionDefinitionKind() == FDK_Definition) { + // [6.9.1/3] qualified void return is invalid on a C + // function definition. Apparently ok on declarations and + // in C++ though (!) + S.Diag(DeclType.Loc, diag::err_func_returning_qualified_void) << T; + } else + diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex); + } // Objective-C ARC ownership qualifiers are ignored on the function // return type (by type canonicalization). Complain if this attribute @@ -3424,8 +3481,6 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { case AttributedType::attr_pcs: case AttributedType::attr_pcs_vfp: return AttributeList::AT_Pcs; - case AttributedType::attr_pnaclcall: - return AttributeList::AT_PnaclCall; case AttributedType::attr_inteloclbicc: return AttributeList::AT_IntelOclBicc; case AttributedType::attr_ms_abi: @@ -4454,8 +4509,6 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { .Case("aapcs", AttributedType::attr_pcs) .Case("aapcs-vfp", AttributedType::attr_pcs_vfp); } - case AttributeList::AT_PnaclCall: - return AttributedType::attr_pnaclcall; case AttributeList::AT_IntelOclBicc: return AttributedType::attr_inteloclbicc; case AttributeList::AT_MSABI: @@ -5086,14 +5139,18 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, /// \param D The definition of the entity. /// \param Suggested Filled in with the declaration that should be made visible /// in order to provide a definition of this entity. -static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) { +bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested) { // Easy case: if we don't have modules, all declarations are visible. - if (!S.getLangOpts().Modules) + if (!getLangOpts().Modules) return true; // If this definition was instantiated from a template, map back to the // pattern from which it was instantiated. - if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { + if (isa<TagDecl>(D) && cast<TagDecl>(D)->isBeingDefined()) { + // We're in the middle of defining it; this definition should be treated + // as visible. + return true; + } else if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { if (auto *Pattern = RD->getTemplateInstantiationPattern()) RD = Pattern; D = RD->getDefinition(); @@ -5104,7 +5161,7 @@ static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) { // If the enum has a fixed underlying type, any declaration of it will do. *Suggested = nullptr; for (auto *Redecl : ED->redecls()) { - if (LookupResult::isVisible(S, Redecl)) + if (LookupResult::isVisible(*this, Redecl)) return true; if (Redecl->isThisDeclarationADefinition() || (Redecl->isCanonicalDecl() && !*Suggested)) @@ -5119,7 +5176,7 @@ static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) { // FIXME: If we merged any other decl into D, and that declaration is visible, // then we should consider a definition to be visible. *Suggested = D; - return LookupResult::isVisible(S, D); + return LookupResult::isVisible(*this, D); } /// Locks in the inheritance model for the given class and all of its bases. @@ -5170,13 +5227,13 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // If we know about the definition but it is not visible, complain. NamedDecl *SuggestedDef = nullptr; if (!Diagnoser.Suppressed && Def && - !hasVisibleDefinition(*this, Def, &SuggestedDef)) { + !hasVisibleDefinition(Def, &SuggestedDef)) { // Suppress this error outside of a SFINAE context if we've already // emitted the error once for this type. There's no usefulness in // repeating the diagnostic. // FIXME: Add a Fix-It that imports the corresponding module or includes // the header. - Module *Owner = SuggestedDef->getOwningModule(); + Module *Owner = getOwningModule(SuggestedDef); Diag(Loc, diag::err_module_private_definition) << T << Owner->getFullModuleName(); Diag(SuggestedDef->getLocation(), diag::note_previous_definition); diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index 36abbb6..f5249fd 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -619,11 +619,6 @@ public: StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E); - - typedef std::pair<ExprResult, QualType> InitCaptureInfoTy; - /// \brief Transform the captures and body of a lambda expression. - ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator, - ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes); TemplateParameterList *TransformTemplateParameterList( TemplateParameterList *TPL) { @@ -1702,7 +1697,7 @@ public: } StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, Stmt *Block) { - return getSema().ActOnSEHFinallyBlock(Loc, Block); + return SEHFinallyStmt::Create(getSema().getASTContext(), Loc, Block); } /// \brief Build a new predefined expression. @@ -1870,11 +1865,9 @@ public: return ExprError(); Base = BaseResult.get(); ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind(); - MemberExpr *ME = - new (getSema().Context) MemberExpr(Base, isArrow, - Member, MemberNameInfo, - cast<FieldDecl>(Member)->getType(), - VK, OK_Ordinary); + MemberExpr *ME = new (getSema().Context) + MemberExpr(Base, isArrow, OpLoc, Member, MemberNameInfo, + cast<FieldDecl>(Member)->getType(), VK, OK_Ordinary); return ME; } @@ -2625,6 +2618,31 @@ public: RBracLoc, Args); } + /// \brief Build a new Objective-C instance/class message to 'super'. + ExprResult RebuildObjCMessageExpr(SourceLocation SuperLoc, + Selector Sel, + ArrayRef<SourceLocation> SelectorLocs, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + MultiExprArg Args, + SourceLocation RBracLoc) { + ObjCInterfaceDecl *Class = Method->getClassInterface(); + QualType ReceiverTy = SemaRef.Context.getObjCInterfaceType(Class); + + return Method->isInstanceMethod() ? SemaRef.BuildInstanceMessage(nullptr, + ReceiverTy, + SuperLoc, + Sel, Method, LBracLoc, SelectorLocs, + RBracLoc, Args) + : SemaRef.BuildClassMessage(nullptr, + ReceiverTy, + SuperLoc, + Sel, Method, LBracLoc, SelectorLocs, + RBracLoc, Args); + + + } + /// \brief Build a new Objective-C ivar reference expression. /// /// By default, performs semantic analysis to build the new expression. @@ -6647,7 +6665,16 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective( if (!D->getAssociatedStmt()) { return StmtError(); } - AssociatedStmt = getDerived().TransformStmt(D->getAssociatedStmt()); + getDerived().getSema().ActOnOpenMPRegionStart(D->getDirectiveKind(), + /*CurScope=*/nullptr); + StmtResult Body; + { + Sema::CompoundScopeRAII CompoundScope(getSema()); + Body = getDerived().TransformStmt( + cast<CapturedStmt>(D->getAssociatedStmt())->getCapturedStmt()); + } + AssociatedStmt = + getDerived().getSema().ActOnOpenMPRegionEnd(Body, TClauses); if (AssociatedStmt.isInvalid()) { return StmtError(); } @@ -7834,6 +7861,9 @@ TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { + if (InitListExpr *Syntactic = E->getSyntacticForm()) + E = Syntactic; + bool InitChanged = false; SmallVector<Expr*, 4> Inits; @@ -7841,8 +7871,12 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { Inits, &InitChanged)) return ExprError(); - if (!getDerived().AlwaysRebuild() && !InitChanged) - return E; + if (!getDerived().AlwaysRebuild() && !InitChanged) { + // FIXME: Attempt to reuse the existing syntactic form of the InitListExpr + // in some cases. We can't reuse it in general, because the syntactic and + // semantic forms are linked, and we can't know that semantic form will + // match even if the syntactic form does. + } return getDerived().RebuildInitList(E->getLBraceLoc(), Inits, E->getRBraceLoc(), E->getType()); @@ -9092,13 +9126,14 @@ ExprResult TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Transform any init-capture expressions before entering the scope of the // lambda body, because they are not semantically within that scope. + typedef std::pair<ExprResult, QualType> InitCaptureInfoTy; SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes; InitCaptureExprsAndTypes.resize(E->explicit_capture_end() - - E->explicit_capture_begin()); + E->explicit_capture_begin()); for (LambdaExpr::capture_iterator C = E->capture_begin(), CEnd = E->capture_end(); C != CEnd; ++C) { - if (!C->isInitCapture()) + if (!E->isInitCapture(C)) continue; EnterExpressionEvaluationContext EEEC(getSema(), Sema::PotentiallyEvaluated); @@ -9120,12 +9155,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { std::make_pair(NewExprInitResult, NewInitCaptureType); } - LambdaScopeInfo *LSI = getSema().PushLambdaScope(); - Sema::FunctionScopeRAII FuncScopeCleanup(getSema()); - // Transform the template parameters, and add them to the current // instantiation scope. The null case is handled correctly. - LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList( + auto TPL = getDerived().TransformTemplateParameterList( E->getTemplateParameterList()); // Transform the type of the original lambda's call operator. @@ -9153,6 +9185,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { NewCallOpType); } + LambdaScopeInfo *LSI = getSema().PushLambdaScope(); + Sema::FunctionScopeRAII FuncScopeCleanup(getSema()); + LSI->GLTemplateParameterList = TPL; + // Create the local class that will describe the lambda. CXXRecordDecl *Class = getSema().createLambdaClosureType(E->getIntroducerRange(), @@ -9169,34 +9205,22 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { LSI->CallOperator = NewCallOperator; getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); - - // TransformLambdaScope will manage the function scope, so we can disable the - // cleanup. - FuncScopeCleanup.disable(); - - return getDerived().TransformLambdaScope(E, NewCallOperator, - InitCaptureExprsAndTypes); -} - -template<typename Derived> -ExprResult -TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, - CXXMethodDecl *CallOperator, - ArrayRef<InitCaptureInfoTy> InitCaptureExprsAndTypes) { - bool Invalid = false; + getDerived().transformedLocalDecl(E->getCallOperator(), NewCallOperator); // Introduce the context of the call operator. - Sema::ContextRAII SavedContext(getSema(), CallOperator, + Sema::ContextRAII SavedContext(getSema(), NewCallOperator, /*NewThisContext*/false); - LambdaScopeInfo *const LSI = getSema().getCurLambda(); // Enter the scope of the lambda. - getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(), - E->getCaptureDefault(), - E->getCaptureDefaultLoc(), - E->hasExplicitParameters(), - E->hasExplicitResultType(), - E->isMutable()); + getSema().buildLambdaScope(LSI, NewCallOperator, + E->getIntroducerRange(), + E->getCaptureDefault(), + E->getCaptureDefaultLoc(), + E->hasExplicitParameters(), + E->hasExplicitResultType(), + E->isMutable()); + + bool Invalid = false; // Transform captures. bool FinishedExplicitCaptures = false; @@ -9221,8 +9245,7 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, continue; // Rebuild init-captures, including the implied field declaration. - if (C->isInitCapture()) { - + if (E->isInitCapture(C)) { InitCaptureInfoTy InitExprTypePair = InitCaptureExprsAndTypes[C - E->capture_begin()]; ExprResult Init = InitExprTypePair.first; @@ -9309,28 +9332,34 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, if (!FinishedExplicitCaptures) getSema().finishLambdaExplicitCaptures(LSI); - // Enter a new evaluation context to insulate the lambda from any // cleanups from the enclosing full-expression. getSema().PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); - if (Invalid) { - getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr, - /*IsInstantiation=*/true); - return ExprError(); - } - // Instantiate the body of the lambda expression. - StmtResult Body = getDerived().TransformStmt(E->getBody()); + StmtResult Body = + Invalid ? StmtError() : getDerived().TransformStmt(E->getBody()); + + // ActOnLambda* will pop the function scope for us. + FuncScopeCleanup.disable(); + if (Body.isInvalid()) { + SavedContext.pop(); getSema().ActOnLambdaError(E->getLocStart(), /*CurScope=*/nullptr, /*IsInstantiation=*/true); return ExprError(); } - return getSema().ActOnLambdaExpr(E->getLocStart(), Body.get(), - /*CurScope=*/nullptr, - /*IsInstantiation=*/true); + // Copy the LSI before ActOnFinishFunctionBody removes it. + // FIXME: This is dumb. Store the lambda information somewhere that outlives + // the call operator. + auto LSICopy = *LSI; + getSema().ActOnFinishFunctionBody(NewCallOperator, Body.get(), + /*IsInstantiation*/ true); + SavedContext.pop(); + + return getSema().BuildLambdaExpr(E->getLocStart(), Body.get()->getLocEnd(), + &LSICopy); } template<typename Derived> @@ -10042,6 +10071,19 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { Args, E->getRightLoc()); } + else if (E->getReceiverKind() == ObjCMessageExpr::SuperClass || + E->getReceiverKind() == ObjCMessageExpr::SuperInstance) { + // Build a new class message send to 'super'. + SmallVector<SourceLocation, 16> SelLocs; + E->getSelectorLocs(SelLocs); + return getDerived().RebuildObjCMessageExpr(E->getSuperLoc(), + E->getSelector(), + SelLocs, + E->getMethodDecl(), + E->getLeftLoc(), + Args, + E->getRightLoc()); + } // Instance message: transform the receiver assert(E->getReceiverKind() == ObjCMessageExpr::Instance && @@ -10720,11 +10762,9 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, !BaseType->getAs<PointerType>()->getPointeeType() ->template getAs<RecordType>())){ // This pseudo-destructor expression is still a pseudo-destructor. - return SemaRef.BuildPseudoDestructorExpr(Base, OperatorLoc, - isArrow? tok::arrow : tok::period, - SS, ScopeType, CCLoc, TildeLoc, - Destroyed, - /*FIXME?*/true); + return SemaRef.BuildPseudoDestructorExpr( + Base, OperatorLoc, isArrow ? tok::arrow : tok::period, SS, ScopeType, + CCLoc, TildeLoc, Destroyed); } TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo(); |