diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
41 files changed, 9392 insertions, 3972 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp index f2ff48a..5f74343 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -34,7 +34,6 @@ #include "clang/Analysis/CFGStmtMap.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" -#include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" @@ -99,7 +98,7 @@ namespace { } } }; -} +} // anonymous namespace /// CheckUnreachable - Check for unreachable code. static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { @@ -157,12 +156,45 @@ public: << DiagRange << isAlwaysTrue; } }; -} // namespace +} // anonymous namespace //===----------------------------------------------------------------------===// // Check for infinite self-recursion in functions //===----------------------------------------------------------------------===// +// Returns true if the function is called anywhere within the CFGBlock. +// For member functions, the additional condition of being call from the +// this pointer is required. +static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) { + // Process all the Stmt's in this block to find any calls to FD. + for (const auto &B : Block) { + if (B.getKind() != CFGElement::Statement) + continue; + + const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt()); + if (!CE || !CE->getCalleeDecl() || + CE->getCalleeDecl()->getCanonicalDecl() != FD) + continue; + + // Skip function calls which are qualified with a templated class. + if (const DeclRefExpr *DRE = + dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) { + if (NestedNameSpecifier *NNS = DRE->getQualifier()) { + if (NNS->getKind() == NestedNameSpecifier::TypeSpec && + isa<TemplateSpecializationType>(NNS->getAsType())) { + continue; + } + } + } + + const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE); + if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) || + !MCE->getMethodDecl()->isVirtual()) + return true; + } + return false; +} + // All blocks are in one of three states. States are ordered so that blocks // can only move to higher states. enum RecursiveState { @@ -171,68 +203,56 @@ enum RecursiveState { FoundPathWithNoRecursiveCall }; -static void checkForFunctionCall(Sema &S, const FunctionDecl *FD, - CFGBlock &Block, unsigned ExitID, - llvm::SmallVectorImpl<RecursiveState> &States, - RecursiveState State) { - unsigned ID = Block.getBlockID(); +// Returns true if there exists a path to the exit block and every path +// to the exit block passes through a call to FD. +static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) { - // A block's state can only move to a higher state. - if (States[ID] >= State) - return; + const unsigned ExitID = cfg->getExit().getBlockID(); - States[ID] = State; + // Mark all nodes as FoundNoPath, then set the status of the entry block. + SmallVector<RecursiveState, 16> States(cfg->getNumBlockIDs(), FoundNoPath); + States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall; - // Found a path to the exit node without a recursive call. - if (ID == ExitID && State == FoundPathWithNoRecursiveCall) - return; + // Make the processing stack and seed it with the entry block. + SmallVector<CFGBlock *, 16> Stack; + Stack.push_back(&cfg->getEntry()); - if (State == FoundPathWithNoRecursiveCall) { - // If the current state is FoundPathWithNoRecursiveCall, the successors - // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine - // which, process all the Stmt's in this block to find any recursive calls. - for (const auto &B : Block) { - if (B.getKind() != CFGElement::Statement) - continue; + while (!Stack.empty()) { + CFGBlock *CurBlock = Stack.back(); + Stack.pop_back(); - const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt()); - if (CE && CE->getCalleeDecl() && - CE->getCalleeDecl()->getCanonicalDecl() == FD) { - - // Skip function calls which are qualified with a templated class. - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>( - CE->getCallee()->IgnoreParenImpCasts())) { - if (NestedNameSpecifier *NNS = DRE->getQualifier()) { - if (NNS->getKind() == NestedNameSpecifier::TypeSpec && - isa<TemplateSpecializationType>(NNS->getAsType())) { - continue; - } - } - } + unsigned ID = CurBlock->getBlockID(); + RecursiveState CurState = States[ID]; - if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) { - if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) || - !MCE->getMethodDecl()->isVirtual()) { - State = FoundPath; - break; - } - } else { - State = FoundPath; - break; + if (CurState == FoundPathWithNoRecursiveCall) { + // Found a path to the exit node without a recursive call. + if (ExitID == ID) + return false; + + // Only change state if the block has a recursive call. + if (hasRecursiveCallInPath(FD, *CurBlock)) + CurState = FoundPath; + } + + // Loop over successor blocks and add them to the Stack if their state + // changes. + for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I) + if (*I) { + unsigned next_ID = (*I)->getBlockID(); + if (States[next_ID] < CurState) { + States[next_ID] = CurState; + Stack.push_back(*I); } } - } } - for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end(); - I != E; ++I) - if (*I) - checkForFunctionCall(S, FD, **I, ExitID, States, State); + // Return true if the exit node is reachable, and only reachable through + // a recursive call. + return States[ExitID] == FoundPath; } static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, - const Stmt *Body, - AnalysisDeclContext &AC) { + const Stmt *Body, AnalysisDeclContext &AC) { FD = FD->getCanonicalDecl(); // Only run on non-templated functions and non-templated members of @@ -248,15 +268,8 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, if (cfg->getExit().pred_empty()) return; - // Mark all nodes as FoundNoPath, then begin processing the entry block. - llvm::SmallVector<RecursiveState, 16> states(cfg->getNumBlockIDs(), - FoundNoPath); - checkForFunctionCall(S, FD, cfg->getEntry(), cfg->getExit().getBlockID(), - states, FoundPathWithNoRecursiveCall); - - // Check that the exit block is reachable. This prevents triggering the - // warning on functions that do not terminate. - if (states[cfg->getExit().getBlockID()] == FoundPath) + // Emit diagnostic if a recursive function call is detected for all paths. + if (checkForRecursiveFunctionCall(FD, cfg)) S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function); } @@ -492,7 +505,7 @@ struct CheckFallThroughDiagnostics { } }; -} +} // anonymous namespace /// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a /// function that should return a value. Check that we don't fall off the end @@ -600,7 +613,7 @@ public: bool doesContainReference() const { return FoundReference; } }; -} +} // anonymous namespace static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { QualType VariableTy = VD->getType().getCanonicalType(); @@ -643,8 +656,7 @@ static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, CharSourceRange::getCharRange(If->getLocStart(), Then->getLocStart())); if (Else) { - SourceLocation ElseKwLoc = Lexer::getLocForEndOfToken( - Then->getLocEnd(), 0, S.getSourceManager(), S.getLangOpts()); + SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getLocEnd()); Fixit2 = FixItHint::CreateRemoval( SourceRange(ElseKwLoc, Else->getLocEnd())); } @@ -836,7 +848,6 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool alwaysReportSelfInit = false) { - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) { // Inspect the initializer of the variable declaration which is // being referenced prior to its initialization. We emit @@ -1058,7 +1069,7 @@ namespace { Sema &S; llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks; }; -} +} // anonymous namespace static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction) { @@ -1090,8 +1101,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, FM.fillReachableBlocks(Cfg); - for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) { - const CFGBlock *B = *I; + for (const CFGBlock *B : llvm::reverse(*Cfg)) { const Stmt *Label = B->getLabel(); if (!Label || !isa<SwitchCase>(Label)) @@ -1170,7 +1180,6 @@ static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, return false; } - static void diagnoseRepeatedUseOfWeak(Sema &S, const sema::FunctionScopeInfo *CurFn, const Decl *D, @@ -1330,20 +1339,16 @@ class UninitValsDiagReporter : public UninitVariablesHandler { // the same as insertion order. This is needed to obtain a deterministic // order of diagnostics when calling flushDiagnostics(). typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap; - UsesMap *uses; + UsesMap uses; public: - UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {} + UninitValsDiagReporter(Sema &S) : S(S) {} ~UninitValsDiagReporter() override { flushDiagnostics(); } MappedType &getUses(const VarDecl *vd) { - if (!uses) - uses = new UsesMap(); - - MappedType &V = (*uses)[vd]; + MappedType &V = uses[vd]; if (!V.getPointer()) V.setPointer(new UsesVec()); - return V; } @@ -1357,10 +1362,7 @@ public: } void flushDiagnostics() { - if (!uses) - return; - - for (const auto &P : *uses) { + for (const auto &P : uses) { const VarDecl *vd = P.first; const MappedType &V = P.second; @@ -1401,7 +1403,8 @@ public: // Release the uses vector. delete vec; } - delete uses; + + uses.clear(); } private: @@ -1413,7 +1416,7 @@ private: }); } }; -} +} // anonymous namespace namespace clang { namespace { @@ -1431,7 +1434,8 @@ struct SortDiagBySourceLocation { return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); } }; -}} +} // anonymous namespace +} // namespace clang //===----------------------------------------------------------------------===// // -Wthread-safety @@ -1670,7 +1674,6 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { Warnings.emplace_back(std::move(Warning), getNotes()); } - void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName, SourceLocation Loc) override { PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex) @@ -1696,10 +1699,10 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { } void leaveFunction(const FunctionDecl* FD) override { - CurrentFunction = 0; + CurrentFunction = nullptr; } }; -} // namespace +} // anonymous namespace } // namespace threadSafety } // namespace clang @@ -1792,7 +1795,9 @@ public: Warnings.emplace_back(std::move(Warning), OptionalNotes()); } }; -}}} +} // anonymous namespace +} // namespace consumed +} // namespace clang //===----------------------------------------------------------------------===// // AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based @@ -1958,7 +1963,6 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, flushDiagnostics(S, fscope); } - // Warning: check missing 'return' if (P.enableCheckFallThrough) { const CheckFallThroughDiagnostics &CD = @@ -2038,7 +2042,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull); } - if (S.getLangOpts().ObjCARCWeak && + if (S.getLangOpts().ObjCWeak && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart())) diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap()); diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp index 34af6cf..3c61c95 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" @@ -108,6 +109,19 @@ void AttributePool::takePool(AttributeList *pool) { #include "clang/Sema/AttrParsedAttrKinds.inc" +static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName, + AttributeList::Syntax SyntaxUsed) { + // Normalize the attribute name, __foo__ becomes foo. This is only allowable + // for GNU attributes. + bool IsGNU = SyntaxUsed == AttributeList::AS_GNU || + (SyntaxUsed == AttributeList::AS_CXX11 && ScopeName == "gnu"); + if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && + AttrName.endswith("__")) + AttrName = AttrName.slice(2, AttrName.size() - 2); + + return AttrName; +} + AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, const IdentifierInfo *ScopeName, Syntax SyntaxUsed) { @@ -117,13 +131,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, if (ScopeName) FullName += ScopeName->getName(); - // Normalize the attribute name, __foo__ becomes foo. This is only allowable - // for GNU attributes. - bool IsGNU = SyntaxUsed == AS_GNU || (SyntaxUsed == AS_CXX11 && - FullName == "gnu"); - if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && - AttrName.endswith("__")) - AttrName = AttrName.slice(2, AttrName.size() - 2); + AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed); // Ensure that in the case of C++11 attributes, we look for '::foo' if it is // unscoped. @@ -137,8 +145,9 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, unsigned AttributeList::getAttributeSpellingListIndex() const { // Both variables will be used in tablegen generated // attribute spell list index matching code. - StringRef Name = AttrName->getName(); StringRef Scope = ScopeName ? ScopeName->getName() : ""; + StringRef Name = normalizeAttrName(AttrName->getName(), Scope, + (AttributeList::Syntax)SyntaxUsed); #include "clang/Sema/AttrSpellingListIndex.inc" @@ -155,7 +164,7 @@ struct ParsedAttrInfo { bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, const Decl *); bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); - bool (*ExistsInTarget)(const llvm::Triple &T); + bool (*ExistsInTarget)(const TargetInfo &Target); unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); }; @@ -195,8 +204,8 @@ bool AttributeList::isTypeAttr() const { return getInfo(*this).IsType; } -bool AttributeList::existsInTarget(const llvm::Triple &T) const { - return getInfo(*this).ExistsInTarget(T); +bool AttributeList::existsInTarget(const TargetInfo &Target) const { + return getInfo(*this).ExistsInTarget(Target); } bool AttributeList::isKnownToGCC() const { diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index 4adbb2b..d664d87 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -1,4 +1,4 @@ -//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===// +//===--- DeclSpec.cpp - Declaration Specifier Semantic Analysis -----------===// // // The LLVM Compiler Infrastructure // @@ -15,29 +15,19 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" -#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency! #include "clang/Sema/LocInfoType.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Support/ErrorHandling.h" #include <cstring> using namespace clang; -static DiagnosticBuilder Diag(DiagnosticsEngine &D, SourceLocation Loc, - unsigned DiagID) { - return D.Report(Loc, DiagID); -} - - void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) { assert(TemplateId && "NULL template-id annotation?"); Kind = IK_TemplateId; @@ -177,7 +167,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, - SourceLocation ESpecLoc, + SourceRange ESpecRange, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, @@ -212,7 +202,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding(); I.Fun.MutableLoc = MutableLoc.getRawEncoding(); I.Fun.ExceptionSpecType = ESpecType; - I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding(); + I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding(); + I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding(); I.Fun.NumExceptions = 0; I.Fun.Exceptions = nullptr; I.Fun.NoexceptExpr = nullptr; @@ -287,6 +278,7 @@ bool Declarator::isDeclarationOfFunction() const { switch (DS.getTypeSpecType()) { case TST_atomic: case TST_auto: + case TST_auto_type: case TST_bool: case TST_char: case TST_char16: @@ -350,6 +342,11 @@ bool Declarator::isStaticMember() { getName().OperatorFunctionId.Operator)); } +bool Declarator::isCtorOrDtor() { + return (getName().getKind() == UnqualifiedId::IK_ConstructorName) || + (getName().getKind() == UnqualifiedId::IK_DestructorName); +} + bool DeclSpec::hasTagDefinition() const { if (!TypeSpecOwned) return false; @@ -470,6 +467,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_typeofType: case DeclSpec::TST_typeofExpr: return "typeof"; case DeclSpec::TST_auto: return "auto"; + case DeclSpec::TST_auto_type: return "__auto_type"; case DeclSpec::TST_decltype: return "(decltype)"; case DeclSpec::TST_decltype_auto: return "decltype(auto)"; case DeclSpec::TST_underlyingType: return "__underlying_type"; @@ -508,12 +506,12 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, case SCS_extern: case SCS_private_extern: case SCS_static: - if (S.getLangOpts().OpenCLVersion < 120) { - DiagID = diag::err_opencl_unknown_type_specifier; - PrevSpec = getSpecifierName(SC); - return true; - } - break; + if (S.getLangOpts().OpenCLVersion < 120) { + DiagID = diag::err_opencl_unknown_type_specifier; + PrevSpec = getSpecifierName(SC); + return true; + } + break; case SCS_auto: case SCS_register: DiagID = diag::err_opencl_unknown_type_specifier; @@ -925,7 +923,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() { /// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or /// diag::NUM_DIAGNOSTICS if there is no error. After calling this method, /// DeclSpec is guaranteed self-consistent, even if an error occurred. -void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPolicy &Policy) { +void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { // Before possibly changing their values, save specs as written. SaveWrittenBuiltinSpecs(); @@ -946,10 +944,10 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli FixItHint Hints[NumLocs]; SourceLocation FirstLoc; for (unsigned I = 0; I != NumLocs; ++I) { - if (!ExtraLocs[I].isInvalid()) { + if (ExtraLocs[I].isValid()) { if (FirstLoc.isInvalid() || - PP.getSourceManager().isBeforeInTranslationUnit(ExtraLocs[I], - FirstLoc)) + S.getSourceManager().isBeforeInTranslationUnit(ExtraLocs[I], + FirstLoc)) FirstLoc = ExtraLocs[I]; Hints[I] = FixItHint::CreateRemoval(ExtraLocs[I]); } @@ -959,7 +957,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli TypeSpecSign = TSS_unspecified; TypeAltiVecVector = TypeAltiVecPixel = TypeAltiVecBool = false; TypeQualifiers = 0; - Diag(D, TSTLoc, diag::err_decltype_auto_cannot_be_combined) + S.Diag(TSTLoc, diag::err_decltype_auto_cannot_be_combined) << Hints[0] << Hints[1] << Hints[2] << Hints[3] << Hints[4] << Hints[5] << Hints[6] << Hints[7]; } @@ -969,14 +967,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli if (TypeAltiVecBool) { // Sign specifiers are not allowed with vector bool. (PIM 2.1) if (TypeSpecSign != TSS_unspecified) { - Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec) + S.Diag(TSSLoc, diag::err_invalid_vector_bool_decl_spec) << getSpecifierName((TSS)TypeSpecSign); } // Only char/int are valid with vector bool. (PIM 2.1) if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) && (TypeSpecType != TST_int)) || TypeAltiVecPixel) { - Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec) + S.Diag(TSTLoc, diag::err_invalid_vector_bool_decl_spec) << (TypeAltiVecPixel ? "__pixel" : getSpecifierName((TST)TypeSpecType, Policy)); } @@ -984,15 +982,15 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli // 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) + S.Diag(TSWLoc, diag::err_invalid_vector_bool_decl_spec) << getSpecifierName((TSW)TypeSpecWidth); // vector bool long long requires VSX support or ZVector. if ((TypeSpecWidth == TSW_longlong) && - (!PP.getTargetInfo().hasFeature("vsx")) && - (!PP.getTargetInfo().hasFeature("power8-vector")) && - !PP.getLangOpts().ZVector) - Diag(D, TSTLoc, diag::err_invalid_vector_long_long_decl_spec); + (!S.Context.getTargetInfo().hasFeature("vsx")) && + (!S.Context.getTargetInfo().hasFeature("power8-vector")) && + !S.getLangOpts().ZVector) + S.Diag(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) || @@ -1002,20 +1000,20 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli // vector long double and vector long long double are never allowed. // vector double is OK for Power7 and later, and ZVector. if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong) - Diag(D, TSWLoc, diag::err_invalid_vector_long_double_decl_spec); - else if (!PP.getTargetInfo().hasFeature("vsx") && - !PP.getLangOpts().ZVector) - Diag(D, TSTLoc, diag::err_invalid_vector_double_decl_spec); + S.Diag(TSWLoc, diag::err_invalid_vector_long_double_decl_spec); + else if (!S.Context.getTargetInfo().hasFeature("vsx") && + !S.getLangOpts().ZVector) + S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec); } else if (TypeSpecType == TST_float) { // vector float is unsupported for ZVector. - if (PP.getLangOpts().ZVector) - Diag(D, TSTLoc, diag::err_invalid_vector_float_decl_spec); + if (S.getLangOpts().ZVector) + S.Diag(TSTLoc, diag::err_invalid_vector_float_decl_spec); } else if (TypeSpecWidth == TSW_long) { // vector long is unsupported for ZVector and deprecated for AltiVec. - if (PP.getLangOpts().ZVector) - Diag(D, TSWLoc, diag::err_invalid_vector_long_decl_spec); + if (S.getLangOpts().ZVector) + S.Diag(TSWLoc, diag::err_invalid_vector_long_decl_spec); else - Diag(D, TSWLoc, diag::warn_vector_long_decl_spec_combination) + S.Diag(TSWLoc, diag::warn_vector_long_decl_spec_combination) << getSpecifierName((TST)TypeSpecType, Policy); } @@ -1034,7 +1032,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 && TypeSpecType != TST_char && TypeSpecType != TST_wchar) { - Diag(D, TSSLoc, diag::err_invalid_sign_spec) + S.Diag(TSSLoc, diag::err_invalid_sign_spec) << getSpecifierName((TST)TypeSpecType, Policy); // signed double -> double. TypeSpecSign = TSS_unspecified; @@ -1049,9 +1047,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // short -> short int, long long -> long long int. else if (TypeSpecType != TST_int) { - Diag(D, TSWLoc, - TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec - : diag::err_invalid_longlong_spec) + S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; TypeSpecOwned = false; @@ -1061,7 +1057,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // long -> long int. else if (TypeSpecType != TST_int && TypeSpecType != TST_double) { - Diag(D, TSWLoc, diag::err_invalid_long_spec) + S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; TypeSpecOwned = false; @@ -1073,17 +1069,17 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli // disallow their use. Need information about the backend. if (TypeSpecComplex != TSC_unspecified) { if (TypeSpecType == TST_unspecified) { - Diag(D, TSCLoc, diag::ext_plain_complex) + S.Diag(TSCLoc, diag::ext_plain_complex) << FixItHint::CreateInsertion( - PP.getLocForEndOfToken(getTypeSpecComplexLoc()), + S.getLocForEndOfToken(getTypeSpecComplexLoc()), " double"); TypeSpecType = TST_double; // _Complex -> _Complex double. } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) { // Note that this intentionally doesn't include _Complex _Bool. - if (!PP.getLangOpts().CPlusPlus) - Diag(D, TSTLoc, diag::ext_integer_complex); + if (!S.getLangOpts().CPlusPlus) + S.Diag(TSTLoc, diag::ext_integer_complex); } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) { - Diag(D, TSCLoc, diag::err_invalid_complex_spec) + S.Diag(TSCLoc, diag::err_invalid_complex_spec) << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecComplex = TSC_unspecified; } @@ -1100,14 +1096,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli case SCS_static: break; default: - if (PP.getSourceManager().isBeforeInTranslationUnit( + if (S.getSourceManager().isBeforeInTranslationUnit( getThreadStorageClassSpecLoc(), getStorageClassSpecLoc())) - Diag(D, getStorageClassSpecLoc(), + S.Diag(getStorageClassSpecLoc(), diag::err_invalid_decl_spec_combination) << DeclSpec::getSpecifierName(getThreadStorageClassSpec()) << SourceRange(getThreadStorageClassSpecLoc()); else - Diag(D, getThreadStorageClassSpecLoc(), + S.Diag(getThreadStorageClassSpecLoc(), diag::err_invalid_decl_spec_combination) << DeclSpec::getSpecifierName(getStorageClassSpec()) << SourceRange(getStorageClassSpecLoc()); @@ -1121,7 +1117,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli // the type specifier is not optional, but we got 'auto' as a storage // class specifier, then assume this is an attempt to use C++0x's 'auto' // type specifier. - if (PP.getLangOpts().CPlusPlus && + if (S.getLangOpts().CPlusPlus && TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) { TypeSpecType = TST_auto; StorageClassSpec = SCS_unspecified; @@ -1130,17 +1126,17 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli } // Diagnose if we've recovered from an ill-formed 'auto' storage class // specifier in a pre-C++11 dialect of C++. - if (!PP.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto) - Diag(D, TSTLoc, diag::ext_auto_type_specifier); - if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus11 && + if (!S.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto) + S.Diag(TSTLoc, diag::ext_auto_type_specifier); + if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11 && StorageClassSpec == SCS_auto) - Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class) + S.Diag(StorageClassSpecLoc, diag::warn_auto_storage_class) << FixItHint::CreateRemoval(StorageClassSpecLoc); if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) - Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type) + S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type) << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); if (Constexpr_specified) - Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr); + S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr); // C++ [class.friend]p6: // No storage-class-specifier shall appear in the decl-specifier-seq @@ -1164,7 +1160,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli ThreadHint = FixItHint::CreateRemoval(SCLoc); } - Diag(D, SCLoc, diag::err_friend_decl_spec) + S.Diag(SCLoc, diag::err_friend_decl_spec) << SpecName << StorageHint << ThreadHint; ClearStorageClassSpecs(); @@ -1190,7 +1186,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli } FixItHint Hint = FixItHint::CreateRemoval(SCLoc); - Diag(D, SCLoc, diag::err_friend_decl_spec) + S.Diag(SCLoc, diag::err_friend_decl_spec) << Keyword << Hint; FS_virtual_specified = FS_explicit_specified = false; diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index 775fe85..c394d24 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -147,9 +147,12 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) { if (VD->hasLocalStorage()) { switch (VD->getType().isDestructedType()) { case QualType::DK_objc_strong_lifetime: + return ScopePair(diag::note_protected_by_objc_strong_init, + diag::note_exits_objc_strong); + case QualType::DK_objc_weak_lifetime: - return ScopePair(diag::note_protected_by_objc_ownership, - diag::note_exits_objc_ownership); + return ScopePair(diag::note_protected_by_objc_weak_init, + diag::note_exits_objc_weak); case QualType::DK_cxx_destructor: OutDiag = diag::note_exits_dtor; diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 9ecb5a7..0f93421 100644 --- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -107,15 +107,11 @@ void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC) Sources[i]->completeVisibleDeclsMap(DC); } -ExternalLoadResult MultiplexExternalSemaSource:: -FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - SmallVectorImpl<Decl*> &Result) { +void MultiplexExternalSemaSource::FindExternalLexicalDecls( + const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, + SmallVectorImpl<Decl *> &Result) { for(size_t i = 0; i < Sources.size(); ++i) - // FIXME: The semantics of the return result is unclear to me... - Sources[i]->FindExternalLexicalDecls(DC, isKindWeWant, Result); - - return ELR_Success; + Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result); } void MultiplexExternalSemaSource::FindFileRegionDecls(FileID File, diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp index f80eadf..cbd7ef7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp @@ -33,11 +33,14 @@ void FunctionScopeInfo::Clear() { ObjCWarnForNoDesignatedInitChain = false; ObjCIsSecondaryInit = false; ObjCWarnForNoInitDelegation = false; + FirstReturnLoc = SourceLocation(); FirstCXXTryLoc = SourceLocation(); FirstSEHTryLoc = SourceLocation(); SwitchStack.clear(); Returns.clear(); + CoroutinePromise = nullptr; + CoroutineStmts.clear(); ErrorTrap.reset(); PossiblyUnreachableDiags.clear(); WeakObjectUses.clear(); @@ -234,5 +237,4 @@ void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, FunctionScopeInfo::~FunctionScopeInfo() { } BlockScopeInfo::~BlockScopeInfo() { } -LambdaScopeInfo::~LambdaScopeInfo() { } CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { } diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index 18d7e9d..39b8cc9 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -40,7 +40,6 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/Support/CrashRecoveryContext.h" using namespace clang; using namespace sema; @@ -121,8 +120,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, FieldCollector.reset(new CXXFieldCollector()); // Tell diagnostics how to render things from the AST library. - PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, - &Context); + Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context); ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false); @@ -139,10 +137,6 @@ void Sema::addImplicitTypedef(StringRef Name, QualType T) { } void Sema::Initialize() { - // Tell the AST consumer about this Sema object. - Consumer.Initialize(Context); - - // FIXME: Isn't this redundant with the initialization above? if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer)) SC->InitializeSema(*this); @@ -155,6 +149,9 @@ void Sema::Initialize() { // will not be able to merge any duplicate __va_list_tag decls correctly. VAListTagName = PP.getIdentifierInfo("__va_list_tag"); + if (!TUScope) + return; + // Initialize predefined 128-bit integer types, if needed. if (Context.getTargetInfo().hasInt128Type()) { // If either of the 128-bit integer types are unavailable to name lookup, @@ -170,7 +167,7 @@ void Sema::Initialize() { // Initialize predefined Objective-C types: - if (PP.getLangOpts().ObjC1) { + if (getLangOpts().ObjC1) { // If 'SEL' does not yet refer to any declarations, make it refer to the // predefined 'SEL'. DeclarationName SEL = &Context.Idents.get("SEL"); @@ -195,8 +192,8 @@ void Sema::Initialize() { } // Initialize Microsoft "predefined C++ types". - if (PP.getLangOpts().MSVCCompat) { - if (PP.getLangOpts().CPlusPlus && + if (getLangOpts().MSVCCompat) { + if (getLangOpts().CPlusPlus && IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end()) PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class), TUScope); @@ -205,7 +202,7 @@ void Sema::Initialize() { } // Initialize predefined OpenCL types. - if (PP.getLangOpts().OpenCL) { + if (getLangOpts().OpenCL) { addImplicitTypedef("image1d_t", Context.OCLImage1dTy); addImplicitTypedef("image1d_array_t", Context.OCLImage1dArrayTy); addImplicitTypedef("image1d_buffer_t", Context.OCLImage1dBufferTy); @@ -215,6 +212,18 @@ void Sema::Initialize() { addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); if (getLangOpts().OpenCLVersion >= 200) { + addImplicitTypedef("image2d_depth_t", Context.OCLImage2dDepthTy); + addImplicitTypedef("image2d_array_depth_t", + Context.OCLImage2dArrayDepthTy); + addImplicitTypedef("image2d_msaa_t", Context.OCLImage2dMSAATy); + addImplicitTypedef("image2d_array_msaa_t", Context.OCLImage2dArrayMSAATy); + addImplicitTypedef("image2d_msaa_depth_t", Context.OCLImage2dMSAADepthTy); + addImplicitTypedef("image2d_array_msaa_depth_t", + Context.OCLImage2dArrayMSAADepthTy); + addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); + addImplicitTypedef("queue_t", Context.OCLQueueTy); + addImplicitTypedef("ndrange_t", Context.OCLNDRangeTy); + addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy); addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy)); addImplicitTypedef("atomic_uint", Context.getAtomicType(Context.UnsignedIntTy)); @@ -239,6 +248,12 @@ void Sema::Initialize() { } } + if (Context.getTargetInfo().hasBuiltinMSVaList()) { + DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list"); + if (IdResolver.begin(MSVaList) == IdResolver.end()) + PushOnScopeChains(Context.getBuiltinMSVaListDecl(), TUScope); + } + DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list"); if (IdResolver.begin(BuiltinVaList) == IdResolver.end()) PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope); @@ -280,7 +295,7 @@ Sema::~Sema() { /// make the relevant declaration unavailable instead of erroring, do /// so and return true. bool Sema::makeUnavailableInSystemHeader(SourceLocation loc, - StringRef msg) { + UnavailableAttr::ImplicitReason reason) { // If we're not in a function, it's an error. FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext); if (!fn) return false; @@ -296,7 +311,7 @@ bool Sema::makeUnavailableInSystemHeader(SourceLocation loc, // If the function is already unavailable, it's not an error. if (fn->hasAttr<UnavailableAttr>()) return true; - fn->addAttr(UnavailableAttr::CreateImplicit(Context, msg, loc)); + fn->addAttr(UnavailableAttr::CreateImplicit(Context, "", reason, loc)); return true; } @@ -334,6 +349,20 @@ void Sema::PrintStats() const { AnalysisWarnings.PrintStats(); } +void Sema::diagnoseNullableToNonnullConversion(QualType DstType, + QualType SrcType, + SourceLocation Loc) { + Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context); + if (!ExprNullability || *ExprNullability != NullabilityKind::Nullable) + return; + + Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context); + if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull) + return; + + Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType; +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// The result is of the given category. @@ -357,18 +386,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue"); #endif - // Check whether we're implicitly casting from a nullable type to a nonnull - // type. - if (auto exprNullability = E->getType()->getNullability(Context)) { - if (*exprNullability == NullabilityKind::Nullable) { - if (auto typeNullability = Ty->getNullability(Context)) { - if (*typeNullability == NullabilityKind::NonNull) { - Diag(E->getLocStart(), diag::warn_nullability_lost) - << E->getType() << Ty; - } - } - } - } + diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart()); QualType ExprTy = Context.getCanonicalType(E->getType()); QualType TypeTy = Context.getCanonicalType(Ty); @@ -689,6 +707,9 @@ void Sema::ActOnEndOfTranslationUnit() { assert(DelayedDefaultedMemberExceptionSpecs.empty()); assert(DelayedExceptionSpecChecks.empty()); + // All dllexport classes should have been processed already. + assert(DelayedDllExportClasses.empty()); + // Remove file scoped decls that turned out to be used. UnusedFileScopedDecls.erase( std::remove_if(UnusedFileScopedDecls.begin(nullptr, true), @@ -708,8 +729,15 @@ void Sema::ActOnEndOfTranslationUnit() { if (WeakID.second.getUsed()) continue; - Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared) - << WeakID.first; + Decl *PrevDecl = LookupSingleName(TUScope, WeakID.first, SourceLocation(), + LookupOrdinaryName); + if (PrevDecl != nullptr && + !(isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl))) + Diag(WeakID.second.getLocation(), diag::warn_attribute_wrong_decl_type) + << "'weak'" << ExpectedVariableOrFunction; + else + Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared) + << WeakID.first; } if (LangOpts.CPlusPlus11 && @@ -1443,7 +1471,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, // arguments and that it returns something of a reasonable type, // so we can emit a fixit and carry on pretending that E was // actually a CallExpr. - SourceLocation ParenInsertionLoc = PP.getLocForEndOfToken(Range.getEnd()); + SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd()); Diag(Loc, PD) << /*zero-arg*/ 1 << Range << (IsCallableWithAppend(E.get()) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp index 0e973cc..e9772bc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -182,15 +182,20 @@ struct AccessTarget : public AccessedEntity { class SavedInstanceContext { public: + SavedInstanceContext(SavedInstanceContext &&S) + : Target(S.Target), Has(S.Has) { + S.Target = nullptr; + } ~SavedInstanceContext() { - Target.HasInstanceContext = Has; + if (Target) + Target->HasInstanceContext = Has; } private: friend struct AccessTarget; explicit SavedInstanceContext(AccessTarget &Target) - : Target(Target), Has(Target.HasInstanceContext) {} - AccessTarget &Target; + : Target(&Target), Has(Target.HasInstanceContext) {} + AccessTarget *Target; bool Has; }; @@ -1766,7 +1771,7 @@ Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) { case AR_inaccessible: return Sema::AR_inaccessible; case AR_dependent: return Sema::AR_dependent; } - llvm_unreachable("falling off end"); + llvm_unreachable("invalid access result"); } Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp index 5973500..61dfdd3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp @@ -60,8 +60,101 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) { return CFT_Host; } +// * CUDA Call preference table +// +// F - from, +// T - to +// Ph - preference in host mode +// Pd - preference in device mode +// H - handled in (x) +// Preferences: b-best, f-fallback, l-last resort, n-never. +// +// | F | T | Ph | Pd | H | +// |----+----+----+----+-----+ +// | d | d | b | b | (b) | +// | d | g | n | n | (a) | +// | d | h | l | l | (e) | +// | d | hd | f | f | (c) | +// | g | d | b | b | (b) | +// | g | g | n | n | (a) | +// | g | h | l | l | (e) | +// | g | hd | f | f | (c) | +// | h | d | l | l | (e) | +// | h | g | b | b | (b) | +// | h | h | b | b | (b) | +// | h | hd | f | f | (c) | +// | hd | d | l | f | (d) | +// | hd | g | f | n |(d/a)| +// | hd | h | f | l | (d) | +// | hd | hd | b | b | (b) | + +Sema::CUDAFunctionPreference +Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, + const FunctionDecl *Callee) { + assert(getLangOpts().CUDATargetOverloads && + "Should not be called w/o enabled target overloads."); + + assert(Callee && "Callee must be valid."); + CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee); + CUDAFunctionTarget CallerTarget = + (Caller != nullptr) ? IdentifyCUDATarget(Caller) : Sema::CFT_Host; + + // If one of the targets is invalid, the check always fails, no matter what + // the other target is. + if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget) + return CFP_Never; + + // (a) Can't call global from some contexts until we support CUDA's + // dynamic parallelism. + if (CalleeTarget == CFT_Global && + (CallerTarget == CFT_Global || CallerTarget == CFT_Device || + (CallerTarget == CFT_HostDevice && getLangOpts().CUDAIsDevice))) + return CFP_Never; + + // (b) Best case scenarios + if (CalleeTarget == CallerTarget || + (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) || + (CallerTarget == CFT_Global && CalleeTarget == CFT_Device)) + return CFP_Best; + + // (c) Calling HostDevice is OK as a fallback that works for everyone. + if (CalleeTarget == CFT_HostDevice) + return CFP_Fallback; + + // Figure out what should be returned 'last resort' cases. Normally + // those would not be allowed, but we'll consider them if + // CUDADisableTargetCallChecks is true. + CUDAFunctionPreference QuestionableResult = + getLangOpts().CUDADisableTargetCallChecks ? CFP_LastResort : CFP_Never; + + // (d) HostDevice behavior depends on compilation mode. + if (CallerTarget == CFT_HostDevice) { + // Calling a function that matches compilation mode is OK. + // Calling a function from the other side is frowned upon. + if (getLangOpts().CUDAIsDevice) + return CalleeTarget == CFT_Device ? CFP_Fallback : QuestionableResult; + else + return (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global) + ? CFP_Fallback + : QuestionableResult; + } + + // (e) Calling across device/host boundary is not something you should do. + if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) || + (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) || + (CallerTarget == CFT_Global && CalleeTarget == CFT_Host)) + return QuestionableResult; + + llvm_unreachable("All cases should've been handled by now."); +} + bool Sema::CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee) { + // With target overloads enabled, we only disallow calling + // combinations with CFP_Never. + if (getLangOpts().CUDATargetOverloads) + return IdentifyCUDAPreference(Caller,Callee) == CFP_Never; + // The CUDADisableTargetCallChecks short-circuits this check: we assume all // cross-target calls are valid. if (getLangOpts().CUDADisableTargetCallChecks) @@ -117,6 +210,57 @@ bool Sema::CheckCUDATarget(const FunctionDecl *Caller, return false; } +template <typename T, typename FetchDeclFn> +static void EraseUnwantedCUDAMatchesImpl(Sema &S, const FunctionDecl *Caller, + llvm::SmallVectorImpl<T> &Matches, + FetchDeclFn FetchDecl) { + assert(S.getLangOpts().CUDATargetOverloads && + "Should not be called w/o enabled target overloads."); + if (Matches.size() <= 1) + return; + + // Find the best call preference among the functions in Matches. + Sema::CUDAFunctionPreference P, BestCFP = Sema::CFP_Never; + for (auto const &Match : Matches) { + P = S.IdentifyCUDAPreference(Caller, FetchDecl(Match)); + if (P > BestCFP) + BestCFP = P; + } + + // Erase all functions with lower priority. + for (unsigned I = 0, N = Matches.size(); I != N;) + if (S.IdentifyCUDAPreference(Caller, FetchDecl(Matches[I])) < BestCFP) { + Matches[I] = Matches[--N]; + Matches.resize(N); + } else { + ++I; + } +} + +void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller, + SmallVectorImpl<FunctionDecl *> &Matches){ + EraseUnwantedCUDAMatchesImpl<FunctionDecl *>( + *this, Caller, Matches, [](const FunctionDecl *item) { return item; }); +} + +void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller, + SmallVectorImpl<DeclAccessPair> &Matches) { + EraseUnwantedCUDAMatchesImpl<DeclAccessPair>( + *this, Caller, Matches, [](const DeclAccessPair &item) { + return dyn_cast<FunctionDecl>(item.getDecl()); + }); +} + +void Sema::EraseUnwantedCUDAMatches( + const FunctionDecl *Caller, + SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){ + EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>( + *this, Caller, Matches, + [](const std::pair<DeclAccessPair, FunctionDecl *> &item) { + return dyn_cast<FunctionDecl>(item.second); + }); +} + /// When an implicitly-declared special member has to invoke more than one /// base/field special member, conflicts may occur in the targets of these /// members. For example, if one base's member __host__ and another's is diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index 9e146ed..f7aace6 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -291,8 +291,10 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD, if (!SD) return false; + SD = SD->getUnderlyingDecl(); + // Namespace and namespace aliases are fine. - if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD)) + if (isa<NamespaceDecl>(SD)) return true; if (!isa<TypeDecl>(SD)) @@ -396,10 +398,7 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, } Found.suppressDiagnostics(); - if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) - return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); - - return false; + return Found.getAsSingle<NamespaceDecl>(); } namespace { @@ -533,6 +532,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, LookupName(Found, S); } + if (Found.isAmbiguous()) + return true; + // If we performed lookup into a dependent context and did not find anything, // that's fine: just build a dependent nested-name-specifier. if (Found.empty() && isDependent && @@ -551,8 +553,6 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, return false; } - // FIXME: Deal with ambiguities cleanly. - if (Found.empty() && !ErrorRecoveryLookup) { // If identifier is not found as class-name-or-namespace-name, but is found // as other entity, don't look for typos. @@ -562,6 +562,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, else if (S && !isDependent) LookupName(R, S); if (!R.empty()) { + // Don't diagnose problems with this speculative lookup. + R.suppressDiagnostics(); // The identifier is found in ordinary lookup. If correction to colon is // allowed, suggest replacement to ':'. if (IsCorrectedToColon) { @@ -604,7 +606,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest) << Name); - if (NamedDecl *ND = Corrected.getCorrectionDecl()) + if (NamedDecl *ND = Corrected.getFoundDecl()) Found.addDecl(ND); Found.setLookupName(Corrected.getCorrection()); } else { @@ -612,7 +614,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, } } - NamedDecl *SD = Found.getAsSingle<NamedDecl>(); + NamedDecl *SD = + Found.isSingleResult() ? Found.getRepresentativeDecl() : nullptr; bool IsExtension = false; bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, &IsExtension); if (!AcceptSpec && IsExtension) { @@ -684,7 +687,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, return false; } - QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); + QualType T = + Context.getTypeDeclType(cast<TypeDecl>(SD->getUnderlyingDecl())); TypeLocBuilder TLB; if (isa<InjectedClassNameType>(T)) { InjectedClassNameTypeLoc InjectedTL diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp index c0754ba..07b0589 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp @@ -160,19 +160,19 @@ static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, unsigned &msg); static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, - const SourceRange &OpRange, + SourceRange OpRange, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath); static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, bool CStyle, - const SourceRange &OpRange, + SourceRange OpRange, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath); static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, bool CStyle, - const SourceRange &OpRange, + SourceRange OpRange, QualType OrigSrcType, QualType OrigDestType, unsigned &msg, CastKind &Kind, @@ -180,7 +180,7 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType,bool CStyle, - const SourceRange &OpRange, + SourceRange OpRange, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath); @@ -188,13 +188,13 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExp static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, Sema::CheckedConversionKind CCK, - const SourceRange &OpRange, + SourceRange OpRange, unsigned &msg, CastKind &Kind, bool ListInitialization); static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, Sema::CheckedConversionKind CCK, - const SourceRange &OpRange, + SourceRange OpRange, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath, bool ListInitialization); @@ -203,7 +203,7 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr, unsigned &msg); static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, - const SourceRange &OpRange, + SourceRange OpRange, unsigned &msg, CastKind &Kind); @@ -489,9 +489,9 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, QualType *TheOffendingDestType = nullptr, Qualifiers *CastAwayQualifiers = nullptr) { // If the only checking we care about is for Objective-C lifetime qualifiers, - // and we're not in ARC mode, there's nothing to check. + // and we're not in ObjC mode, there's nothing to check. if (!CheckCVR && CheckObjCLifetime && - !Self.Context.getLangOpts().ObjCAutoRefCount) + !Self.Context.getLangOpts().ObjC1) return false; // Casting away constness is defined in C++ 5.2.11p8 with reference to @@ -683,7 +683,8 @@ void CastOperation::CheckDynamicCast() { // C++ 5.2.7p5 // Upcasts are resolved statically. - if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) { + if (DestRecord && + Self.IsDerivedFrom(OpRange.getBegin(), SrcPointee, DestPointee)) { if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee, OpRange.getBegin(), OpRange, &BasePath)) { @@ -943,7 +944,7 @@ void CastOperation::CheckStaticCast() { static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, Sema::CheckedConversionKind CCK, - const SourceRange &OpRange, unsigned &msg, + SourceRange OpRange, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath, bool ListInitialization) { // Determine whether we have the semantics of a C-style cast. @@ -1171,7 +1172,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, Kind = CK_DerivedToBase; CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); - if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths)) + if (!Self.IsDerivedFrom(SrcExpr->getLocStart(), SrcExpr->getType(), + R->getPointeeType(), Paths)) return TC_NotApplicable; Self.BuildBasePathArray(Paths, BasePath); @@ -1184,7 +1186,7 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, /// Tests whether a conversion according to C++ 5.2.9p5 is valid. TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, - bool CStyle, const SourceRange &OpRange, + bool CStyle, SourceRange OpRange, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath) { // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be @@ -1222,7 +1224,7 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, /// Tests whether a conversion according to C++ 5.2.9p8 is valid. TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, - bool CStyle, const SourceRange &OpRange, + bool CStyle, SourceRange OpRange, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath) { // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class @@ -1256,12 +1258,12 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, /// DestType is possible and allowed. TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, - bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, + bool CStyle, SourceRange OpRange, QualType OrigSrcType, QualType OrigDestType, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath) { // We can only work with complete types. But don't complain if it doesn't work - if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0) || - Self.RequireCompleteType(OpRange.getBegin(), DestType, 0)) + if (!Self.isCompleteType(OpRange.getBegin(), SrcType) || + !Self.isCompleteType(OpRange.getBegin(), DestType)) return TC_NotApplicable; // Downcast can only happen in class hierarchies, so we need classes. @@ -1271,7 +1273,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); - if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) { + if (!Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths)) { return TC_NotApplicable; } @@ -1307,7 +1309,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, if (!Paths.isRecordingPaths()) { Paths.clear(); Paths.setRecordingPaths(true); - Self.IsDerivedFrom(DestType, SrcType, Paths); + Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths); } std::string PathDisplayStr; std::set<unsigned> DisplayedPaths; @@ -1372,7 +1374,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType, bool CStyle, - const SourceRange &OpRange, + SourceRange OpRange, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath) { const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(); @@ -1398,6 +1400,11 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, return TC_NotApplicable; } + // Lock down the inheritance model right now in MS ABI, whether or not the + // pointee types are the same. + if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) + (void)Self.isCompleteType(OpRange.getBegin(), SrcType); + // T == T, modulo cv if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(), DestMemPtr->getPointeeType())) @@ -1408,16 +1415,15 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestClass(DestMemPtr->getClass(), 0); CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); - if (Self.RequireCompleteType(OpRange.getBegin(), SrcClass, 0) || - !Self.IsDerivedFrom(SrcClass, DestClass, Paths)) { + if (!Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths)) return TC_NotApplicable; - } // B is a base of D. But is it an allowed base? If not, it's a hard error. if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) { Paths.clear(); Paths.setRecordingPaths(true); - bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths); + bool StillOkay = + Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths); assert(StillOkay); (void)StillOkay; std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths); @@ -1484,7 +1490,7 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, Sema::CheckedConversionKind CCK, - const SourceRange &OpRange, unsigned &msg, + SourceRange OpRange, unsigned &msg, CastKind &Kind, bool ListInitialization) { if (DestType->isRecordType()) { if (Self.RequireCompleteType(OpRange.getBegin(), DestType, @@ -1494,10 +1500,6 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, msg = 0; return TC_Failed; } - } else if (DestType->isMemberPointerType()) { - if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) { - Self.RequireCompleteType(OpRange.getBegin(), DestType, 0); - } } InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); @@ -1750,7 +1752,7 @@ static void checkIntToPointerCast(bool CStyle, SourceLocation Loc, static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, - const SourceRange &OpRange, + SourceRange OpRange, unsigned &msg, CastKind &Kind) { bool IsLValueCast = false; @@ -1845,8 +1847,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) { // We need to determine the inheritance model that the class will use if // haven't yet. - Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0); - Self.RequireCompleteType(OpRange.getBegin(), DestType, 0); + (void)Self.isCompleteType(OpRange.getBegin(), SrcType); + (void)Self.isCompleteType(OpRange.getBegin(), DestType); } // Don't allow casting between member pointers of different sizes. @@ -1877,28 +1879,29 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return TC_Success; } + // Allow reinterpret_casts between vectors of the same size and + // between vectors and integers of the same size. bool destIsVector = DestType->isVectorType(); bool srcIsVector = SrcType->isVectorType(); if (srcIsVector || destIsVector) { - // FIXME: Should this also apply to floating point types? - bool srcIsScalar = SrcType->isIntegralType(Self.Context); - bool destIsScalar = DestType->isIntegralType(Self.Context); - - // Check if this is a cast between a vector and something else. - if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) && - !(srcIsVector && destIsVector)) + // The non-vector type, if any, must have integral type. This is + // the same rule that C vector casts use; note, however, that enum + // types are not integral in C++. + if ((!destIsVector && !DestType->isIntegralType(Self.Context)) || + (!srcIsVector && !SrcType->isIntegralType(Self.Context))) return TC_NotApplicable; - // If both types have the same size, we can successfully cast. - if (Self.Context.getTypeSize(SrcType) - == Self.Context.getTypeSize(DestType)) { + // The size we want to consider is eltCount * eltSize. + // That's exactly what the lax-conversion rules will check. + if (Self.areLaxCompatibleVectorTypes(SrcType, DestType)) { Kind = CK_BitCast; return TC_Success; } - - if (destIsScalar) + + // Otherwise, pick a reasonable diagnostic. + if (!destIsVector) msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size; - else if (srcIsScalar) + else if (!srcIsVector) msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size; else msg = diag::err_bad_cxx_cast_vector_to_vector_different_size; @@ -2237,6 +2240,16 @@ void CastOperation::CheckCStyleCast() { return; } + // Overloads are allowed with C extensions, so we need to support them. + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + DeclAccessPair DAP; + if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction( + SrcExpr.get(), DestType, /*Complain=*/true, DAP)) + SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD); + else + return; + assert(SrcExpr.isUsable()); + } SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); if (SrcExpr.isInvalid()) return; @@ -2480,8 +2493,11 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false); if (Op.SrcExpr.isInvalid()) return ExprError(); - - if (CXXConstructExpr *ConstructExpr = dyn_cast<CXXConstructExpr>(Op.SrcExpr.get())) + + auto *SubExpr = Op.SrcExpr.get(); + if (auto *BindExpr = dyn_cast<CXXBindTemporaryExpr>(SubExpr)) + SubExpr = BindExpr->getSubExpr(); + if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr)) ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc)); return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 1a8ab6e..59d51f7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/Analysis/Analyses/FormatString.h" @@ -111,6 +112,39 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) { return false; } +static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { + if (checkArgCount(S, TheCall, 3)) + return true; + + // First two arguments should be integers. + for (unsigned I = 0; I < 2; ++I) { + Expr *Arg = TheCall->getArg(I); + QualType Ty = Arg->getType(); + if (!Ty->isIntegerType()) { + S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_int) + << Ty << Arg->getSourceRange(); + return true; + } + } + + // Third argument should be a pointer to a non-const integer. + // IRGen correctly handles volatile, restrict, and address spaces, and + // the other qualifiers aren't possible. + { + Expr *Arg = TheCall->getArg(2); + QualType Ty = Arg->getType(); + const auto *PtrTy = Ty->getAs<PointerType>(); + if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() && + !PtrTy->getPointeeType().isConstQualified())) { + S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_ptr_int) + << Ty << Arg->getSourceRange(); + return true; + } + } + + return false; +} + static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl, CallExpr *TheCall, unsigned SizeIdx, unsigned DstSizeIdx) { @@ -440,6 +474,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__sync_swap_8: case Builtin::BI__sync_swap_16: return SemaBuiltinAtomicOverloaded(TheCallResult); + case Builtin::BI__builtin_nontemporal_load: + case Builtin::BI__builtin_nontemporal_store: + return SemaBuiltinNontemporalOverloaded(TheCallResult); #define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ case Builtin::BI##ID: \ @@ -453,6 +490,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinAddressof(*this, TheCall)) return ExprError(); break; + case Builtin::BI__builtin_add_overflow: + case Builtin::BI__builtin_sub_overflow: + case Builtin::BI__builtin_mul_overflow: + if (SemaBuiltinOverflow(*this, TheCall)) + return ExprError(); + break; case Builtin::BI__builtin_operator_new: case Builtin::BI__builtin_operator_delete: if (!getLangOpts().CPlusPlus) { @@ -525,7 +568,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, // Since the target specific builtins for each arch overlap, only check those // of the arch we are compiling for. - if (BuiltinID >= Builtin::FirstTSBuiltin) { + if (Context.BuiltinInfo.isTSBuiltin(BuiltinID)) { switch (Context.getTargetInfo().getTriple().getArch()) { case llvm::Triple::arm: case llvm::Triple::armeb: @@ -1027,12 +1070,34 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, return SemaBuiltinConstantArgRange(TheCall, i, l, u); } +/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *). +/// This checks that the target supports __builtin_cpu_supports and +/// that the string argument is constant and valid. +static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) { + Expr *Arg = TheCall->getArg(0); + + // Check if the argument is a string literal. + if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) + return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal) + << Arg->getSourceRange(); + + // Check the contents of the string. + StringRef Feature = + cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); + if (!S.Context.getTargetInfo().validateCpuSupports(Feature)) + return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports) + << Arg->getSourceRange(); + return false; +} + bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { unsigned i = 0, l = 0, u = 0; switch (BuiltinID) { default: return false; case X86::BI__builtin_cpu_supports: - return SemaBuiltinCpuSupports(TheCall); + return SemaBuiltinCpuSupports(*this, TheCall); + case X86::BI__builtin_ms_va_start: + return SemaBuiltinMSVAStart(TheCall); 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: @@ -1115,8 +1180,7 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, /// Checks if a the given expression evaluates to null. /// /// \brief Returns true if the value evaluates to null. -static bool CheckNonNullExpr(Sema &S, - const Expr *Expr) { +static bool CheckNonNullExpr(Sema &S, const Expr *Expr) { // If the expression has non-null type, it doesn't evaluate to null. if (auto nullability = Expr->IgnoreImplicit()->getType()->getNullability(S.Context)) { @@ -1145,7 +1209,8 @@ static void CheckNonNullArgument(Sema &S, const Expr *ArgExpr, SourceLocation CallSiteLoc) { if (CheckNonNullExpr(S, ArgExpr)) - S.Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); + S.DiagRuntimeBehavior(CallSiteLoc, ArgExpr, + S.PDiag(diag::warn_null_arg) << ArgExpr->getSourceRange()); } bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) { @@ -1638,6 +1703,12 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, return ExprError(); } ValType = AtomTy->getAs<AtomicType>()->getValueType(); + } else if (Form != Load && Op != AtomicExpr::AO__atomic_load) { + if (ValType.isConstQualified()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer) + << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } } // For an arithmetic operation, the implied arithmetic must be well-formed. @@ -1675,9 +1746,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, return ExprError(); } - // FIXME: For any builtin other than a load, the ValType must not be - // const-qualified. - switch (ValType.getObjCLifetime()) { case Qualifiers::OCL_None: case Qualifiers::OCL_ExplicitNone: @@ -1710,6 +1778,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, if (!IsC11 && !IsN) ByValType = Ptr->getType(); + // FIXME: __atomic_load allows the first argument to be a a pointer to const + // but not the second argument. We need to manually remove possible const + // qualifiers. + // The first argument --- the pointer --- has a fixed type; we // deduce the types of the rest of the arguments accordingly. Walk // the remaining arguments, converting them to the deduced value type. @@ -1729,8 +1801,17 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, Ty = ByValType; else if (Form == Arithmetic) Ty = Context.getPointerDiffType(); - else - Ty = Context.getPointerType(ValType.getUnqualifiedType()); + else { + Expr *ValArg = TheCall->getArg(i); + unsigned AS = 0; + // Keep address space of non-atomic pointer type. + if (const PointerType *PtrTy = + ValArg->getType()->getAs<PointerType>()) { + AS = PtrTy->getPointeeType().getAddressSpace(); + } + Ty = Context.getPointerType( + Context.getAddrSpaceQualType(ValType.getUnqualifiedType(), AS)); + } break; case 2: // The third argument to compare_exchange / GNU exchange is a @@ -2142,7 +2223,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // Get the decl for the concrete builtin from this, we can tell what the // concrete integer type we should convert to is. unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex]; - const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID); + const char *NewBuiltinName = Context.BuiltinInfo.getName(NewBuiltinID); FunctionDecl *NewBuiltinDecl; if (NewBuiltinID == BuiltinID) NewBuiltinDecl = FDecl; @@ -2209,6 +2290,78 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { return TheCallResult; } +/// SemaBuiltinNontemporalOverloaded - We have a call to +/// __builtin_nontemporal_store or __builtin_nontemporal_load, which is an +/// overloaded function based on the pointer type of its last argument. +/// +/// This function goes through and does final semantic checking for these +/// builtins. +ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) { + CallExpr *TheCall = (CallExpr *)TheCallResult.get(); + DeclRefExpr *DRE = + cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); + FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl()); + unsigned BuiltinID = FDecl->getBuiltinID(); + assert((BuiltinID == Builtin::BI__builtin_nontemporal_store || + BuiltinID == Builtin::BI__builtin_nontemporal_load) && + "Unexpected nontemporal load/store builtin!"); + bool isStore = BuiltinID == Builtin::BI__builtin_nontemporal_store; + unsigned numArgs = isStore ? 2 : 1; + + // Ensure that we have the proper number of arguments. + if (checkArgCount(*this, TheCall, numArgs)) + return ExprError(); + + // Inspect the last argument of the nontemporal builtin. This should always + // be a pointer type, from which we imply the type of the memory access. + // Because it is a pointer type, we don't have to worry about any implicit + // casts here. + Expr *PointerArg = TheCall->getArg(numArgs - 1); + ExprResult PointerArgResult = + DefaultFunctionArrayLvalueConversion(PointerArg); + + if (PointerArgResult.isInvalid()) + return ExprError(); + PointerArg = PointerArgResult.get(); + TheCall->setArg(numArgs - 1, PointerArg); + + const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>(); + if (!pointerType) { + Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_must_be_pointer) + << PointerArg->getType() << PointerArg->getSourceRange(); + return ExprError(); + } + + QualType ValType = pointerType->getPointeeType(); + + // Strip any qualifiers off ValType. + ValType = ValType.getUnqualifiedType(); + if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && + !ValType->isBlockPointerType() && !ValType->isFloatingType() && + !ValType->isVectorType()) { + Diag(DRE->getLocStart(), + diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector) + << PointerArg->getType() << PointerArg->getSourceRange(); + return ExprError(); + } + + if (!isStore) { + TheCall->setType(ValType); + return TheCallResult; + } + + ExprResult ValArg = TheCall->getArg(0); + InitializedEntity Entity = InitializedEntity::InitializeParameter( + Context, ValType, /*consume*/ false); + ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg); + if (ValArg.isInvalid()) + return ExprError(); + + TheCall->setArg(0, ValArg.get()); + TheCall->setType(Context.VoidTy); + return TheCallResult; +} + /// CheckObjCString - Checks that the argument to the builtin /// CFString constructor is correct /// Note: It might also make sense to do the UTF-16 conversion here (would @@ -2241,9 +2394,10 @@ bool Sema::CheckObjCString(Expr *Arg) { return false; } -/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity. -/// Emit an error and return true on failure, return false on success. -bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { +/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' +/// for validity. Emit an error and return true on failure; return false +/// on success. +bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) { Expr *Fn = TheCall->getCallee(); if (TheCall->getNumArgs() > 2) { Diag(TheCall->getArg(2)->getLocStart(), @@ -2321,6 +2475,48 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { return false; } +/// Check the arguments to '__builtin_va_start' for validity, and that +/// it was called from a function of the native ABI. +/// Emit an error and return true on failure; return false on success. +bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { + // On x86-64 Unix, don't allow this in Win64 ABI functions. + // On x64 Windows, don't allow this in System V ABI functions. + // (Yes, that means there's no corresponding way to support variadic + // System V ABI functions on Windows.) + if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64) { + unsigned OS = Context.getTargetInfo().getTriple().getOS(); + clang::CallingConv CC = CC_C; + if (const FunctionDecl *FD = getCurFunctionDecl()) + CC = FD->getType()->getAs<FunctionType>()->getCallConv(); + if ((OS == llvm::Triple::Win32 && CC == CC_X86_64SysV) || + (OS != llvm::Triple::Win32 && CC == CC_X86_64Win64)) + return Diag(TheCall->getCallee()->getLocStart(), + diag::err_va_start_used_in_wrong_abi_function) + << (OS != llvm::Triple::Win32); + } + return SemaBuiltinVAStartImpl(TheCall); +} + +/// Check the arguments to '__builtin_ms_va_start' for validity, and that +/// it was called from a Win64 ABI function. +/// Emit an error and return true on failure; return false on success. +bool Sema::SemaBuiltinMSVAStart(CallExpr *TheCall) { + // This only makes sense for x86-64. + const llvm::Triple &TT = Context.getTargetInfo().getTriple(); + Expr *Callee = TheCall->getCallee(); + if (TT.getArch() != llvm::Triple::x86_64) + return Diag(Callee->getLocStart(), diag::err_x86_builtin_32_bit_tgt); + // Don't allow this in System V ABI functions. + clang::CallingConv CC = CC_C; + if (const FunctionDecl *FD = getCurFunctionDecl()) + CC = FD->getType()->getAs<FunctionType>()->getCallConv(); + if (CC == CC_X86_64SysV || + (TT.getOS() != llvm::Triple::Win32 && CC != CC_X86_64Win64)) + return Diag(Callee->getLocStart(), + diag::err_ms_va_start_used_in_sysv_function); + return SemaBuiltinVAStartImpl(TheCall); +} + bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) { // void __va_start(va_list *ap, const char *named_addr, size_t slot_size, // const char *named_addr); @@ -2784,26 +2980,6 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, return false; } -/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *). -/// This checks that the target supports __builtin_cpu_supports and -/// that the string argument is constant and valid. -bool Sema::SemaBuiltinCpuSupports(CallExpr *TheCall) { - Expr *Arg = TheCall->getArg(0); - - // Check if the argument is a string literal. - if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) - return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal) - << Arg->getSourceRange(); - - // Check the contents of the string. - StringRef Feature = - cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); - if (!Context.getTargetInfo().validateCpuSupports(Feature)) - return Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports) - << Arg->getSourceRange(); - return false; -} - /// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val). /// This checks that the target supports __builtin_longjmp and /// that val is a constant 1. @@ -4833,7 +5009,7 @@ static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range, } } } else { - FunctionName = S.Context.BuiltinInfo.GetName(AbsKind); + FunctionName = S.Context.BuiltinInfo.getName(AbsKind); HeaderName = S.Context.BuiltinInfo.getHeaderName(AbsKind); if (HeaderName) { @@ -4909,7 +5085,7 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, // function call. if (ArgType->isUnsignedIntegerType()) { const char *FunctionName = - IsStdAbs ? "std::abs" : Context.BuiltinInfo.GetName(AbsKind); + IsStdAbs ? "std::abs" : Context.BuiltinInfo.getName(AbsKind); Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType; Diag(Call->getExprLoc(), diag::note_remove_abs) << FunctionName @@ -4917,6 +5093,19 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, return; } + // Taking the absolute value of a pointer is very suspicious, they probably + // wanted to index into an array, dereference a pointer, call a function, etc. + if (ArgType->isPointerType() || ArgType->canDecayToPointerType()) { + unsigned DiagType = 0; + if (ArgType->isFunctionType()) + DiagType = 1; + else if (ArgType->isArrayType()) + DiagType = 2; + + Diag(Call->getExprLoc(), diag::warn_pointer_abs) << DiagType << ArgType; + return; + } + // std::abs has overloads which prevent most of the absolute value problems // from occurring. if (IsStdAbs) @@ -5465,17 +5654,15 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType, } if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var. - S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref - : diag::warn_ret_stack_addr) + S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType() << DR->getDecl()->getDeclName() << diagRange; } else if (isa<BlockExpr>(stackE)) { // local block. S.Diag(diagLoc, diag::err_ret_local_block) << diagRange; } else if (isa<AddrLabelExpr>(stackE)) { // address of label. S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; } else { // local temporary. - S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref - : diag::warn_ret_local_temp_addr) - << diagRange; + S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref) + << lhsType->isReferenceType() << diagRange; } // Display the "trail" of reference variables that we followed until we @@ -5750,6 +5937,11 @@ do { return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl); } + case Stmt::OMPArraySectionExprClass: { + return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars, + ParentDecl); + } + case Stmt::ConditionalOperatorClass: { // For conditional operators we need to see if either the LHS or RHS are // non-NULL Expr's. If one is non-NULL, we return it. @@ -7083,6 +7275,14 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); + + } + // ... or possibly if we're increasing rank, too + else if (TargetBT->getKind() > SourceBT->getKind()) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_double_promotion); } return; } @@ -7105,20 +7305,24 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } } - // If the target is bool, warn if expr is a function or method call. - if (Target->isSpecificBuiltinType(BuiltinType::Bool) && - isa<CallExpr>(E)) { + // Detect the case where a call result is converted from floating-point to + // to bool, and the final argument to the call is converted from bool, to + // discover this typo: + // + // bool b = fabs(x < 1.0); // should be "bool b = fabs(x) < 1.0;" + // + // FIXME: This is an incredibly special case; is there some more general + // way to detect this class of misplaced-parentheses bug? + if (Target->isBooleanType() && isa<CallExpr>(E)) { // Check last argument of function call to see if it is an // implicit cast from a type matching the type the result // is being cast to. CallExpr *CEx = cast<CallExpr>(E); - unsigned NumArgs = CEx->getNumArgs(); - if (NumArgs > 0) { + if (unsigned NumArgs = CEx->getNumArgs()) { Expr *LastA = CEx->getArg(NumArgs - 1); Expr *InnerE = LastA->IgnoreParenImpCasts(); - const Type *InnerType = - S.Context.getCanonicalType(InnerE->getType()).getTypePtr(); - if (isa<ImplicitCastExpr>(LastA) && (InnerType == Target)) { + if (isa<ImplicitCastExpr>(LastA) && + InnerE->getType()->isBooleanType()) { // Warn on this floating-point to bool conversion DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_floating_point_to_bool); @@ -7301,18 +7505,16 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { CheckImplicitConversion(S, E, T, CC); // Now continue drilling into this expression. - - if (PseudoObjectExpr * POE = dyn_cast<PseudoObjectExpr>(E)) { - if (POE->getResultExpr()) - E = POE->getResultExpr(); - } - - if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) { - if (OVE->getSourceExpr()) - AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); - return; + + if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { + // The bound subexpressions in a PseudoObjectExpr are not reachable + // as transitive children. + // FIXME: Use a more uniform representation for this. + for (auto *SE : POE->semantics()) + if (auto *OVE = dyn_cast<OpaqueValueExpr>(SE)) + AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC); } - + // Skip past explicit casts. if (isa<ExplicitCastExpr>(E)) { E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts(); @@ -7372,12 +7574,6 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { } // end anonymous namespace -enum { - AddressOf, - FunctionPointer, - ArrayPointer -}; - // Helper function for Sema::DiagnoseAlwaysNonNullPointer. // Returns true when emitting a warning about taking the address of a reference. static bool CheckForReference(Sema &SemaRef, const Expr *E, @@ -7476,6 +7672,26 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, } } + auto ComplainAboutNonnullParamOrCall = [&](bool IsParam) { + std::string Str; + llvm::raw_string_ostream S(Str); + E->printPretty(S, nullptr, getPrintingPolicy()); + unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare + : diag::warn_cast_nonnull_to_bool; + Diag(E->getExprLoc(), DiagID) << IsParam << S.str() + << E->getSourceRange() << Range << IsEqual; + }; + + // If we have a CallExpr that is tagged with returns_nonnull, we can complain. + if (auto *Call = dyn_cast<CallExpr>(E->IgnoreParenImpCasts())) { + if (auto *Callee = Call->getDirectCallee()) { + if (Callee->hasAttr<ReturnsNonNullAttr>()) { + ComplainAboutNonnullParamOrCall(false); + return; + } + } + } + // Expect to find a single Decl. Skip anything more complicated. ValueDecl *D = nullptr; if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) { @@ -7487,40 +7703,38 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, // Weak Decls can be null. if (!D || D->isWeak()) return; - + // Check for parameter decl with nonnull attribute - if (const ParmVarDecl* PV = dyn_cast<ParmVarDecl>(D)) { - if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV)) - if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) { - unsigned NumArgs = FD->getNumParams(); - llvm::SmallBitVector AttrNonNull(NumArgs); + if (const auto* PV = dyn_cast<ParmVarDecl>(D)) { + if (getCurFunction() && + !getCurFunction()->ModifiedNonNullParams.count(PV)) { + if (PV->hasAttr<NonNullAttr>()) { + ComplainAboutNonnullParamOrCall(true); + return; + } + + if (const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) { + auto ParamIter = std::find(FD->param_begin(), FD->param_end(), PV); + assert(ParamIter != FD->param_end()); + unsigned ParamNo = std::distance(FD->param_begin(), ParamIter); + for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) { if (!NonNull->args_size()) { - AttrNonNull.set(0, NumArgs); - break; - } - for (unsigned Val : NonNull->args()) { - if (Val >= NumArgs) - continue; - AttrNonNull.set(Val); + ComplainAboutNonnullParamOrCall(true); + return; } - } - if (!AttrNonNull.empty()) - for (unsigned i = 0; i < NumArgs; ++i) - if (FD->getParamDecl(i) == PV && - (AttrNonNull[i] || PV->hasAttr<NonNullAttr>())) { - std::string Str; - llvm::raw_string_ostream S(Str); - E->printPretty(S, nullptr, getPrintingPolicy()); - unsigned DiagID = IsCompare ? diag::warn_nonnull_parameter_compare - : diag::warn_cast_nonnull_to_bool; - Diag(E->getExprLoc(), DiagID) << S.str() << E->getSourceRange() - << Range << IsEqual; + + for (unsigned ArgNo : NonNull->args()) { + if (ArgNo == ParamNo) { + ComplainAboutNonnullParamOrCall(true); return; } + } + } } } - + } + QualType T = D->getType(); const bool IsArray = T->isArrayType(); const bool IsFunction = T->isFunctionType(); @@ -7541,7 +7755,11 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare : diag::warn_impcast_pointer_to_bool; - unsigned DiagType; + enum { + AddressOf, + FunctionPointer, + ArrayPointer + } DiagType; if (IsAddressOf) DiagType = AddressOf; else if (IsFunction) @@ -8229,6 +8447,15 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P, } } } + + // Parameters with the pass_object_size attribute only need to be marked + // constant at function definitions. Because we lack information about + // whether we're on a declaration or definition when we're instantiating the + // attribute, we need to check for constness here. + if (const auto *Attr = Param->getAttr<PassObjectSizeAttr>()) + if (!Param->getType().isConstQualified()) + Diag(Param->getLocation(), diag::err_attribute_pointers_only) + << Attr->getSpelling() << 1; } return HasInvalidParm; @@ -8348,7 +8575,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, return; llvm::APSInt index; - if (!IndexExpr->EvaluateAsInt(index, Context)) + if (!IndexExpr->EvaluateAsInt(index, Context, Expr::SE_AllowSideEffects)) return; if (IndexNegated) index = -index; @@ -8462,6 +8689,13 @@ void Sema::CheckArrayAccess(const Expr *expr) { AllowOnePastEnd > 0); return; } + case Stmt::OMPArraySectionExprClass: { + const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr); + if (ASE->getLowerBound()) + CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(), + /*ASE=*/nullptr, AllowOnePastEnd > 0); + return; + } case Stmt::UnaryOperatorClass: { // Only unwrap the * and & unary operators const UnaryOperator *UO = cast<UnaryOperator>(expr); @@ -9672,4 +9906,3 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, << ArgumentExpr->getSourceRange() << TypeTagExpr->getSourceRange(); } - diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index 8626527..21cf625 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -494,6 +494,7 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, bool &AsNestedNameSpecifier) const { AsNestedNameSpecifier = false; + auto *Named = ND; ND = ND->getUnderlyingDecl(); // Skip unnamed entities. @@ -526,14 +527,14 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, return false; if (Filter == &ResultBuilder::IsNestedNameSpecifier || - ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) && + (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace && Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr)) AsNestedNameSpecifier = true; // Filter out any unwanted results. - if (Filter && !(this->*Filter)(ND)) { + if (Filter && !(this->*Filter)(Named)) { // Check whether it is interesting as a nested-name-specifier. if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && IsNestedNameSpecifier(ND) && @@ -1142,14 +1143,12 @@ bool ResultBuilder::IsNamespace(const NamedDecl *ND) const { /// \brief Determines whether the given declaration is a namespace or /// namespace alias. bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const { - return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); + return isa<NamespaceDecl>(ND->getUnderlyingDecl()); } /// \brief Determines whether the given declaration is a type. bool ResultBuilder::IsType(const NamedDecl *ND) const { - if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND)) - ND = Using->getTargetDecl(); - + ND = ND->getUnderlyingDecl(); return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); } @@ -1157,11 +1156,9 @@ bool ResultBuilder::IsType(const NamedDecl *ND) const { /// "." or "->". Only value declarations, nested name specifiers, and /// using declarations thereof should show up. bool ResultBuilder::IsMember(const NamedDecl *ND) const { - if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND)) - ND = Using->getTargetDecl(); - + ND = ND->getUnderlyingDecl(); return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) || - isa<ObjCPropertyDecl>(ND); + isa<ObjCPropertyDecl>(ND); } static bool isObjCReceiverType(ASTContext &C, QualType T) { @@ -3036,6 +3033,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) { case Decl::ParmVar: return CXCursor_ParmDecl; case Decl::Typedef: return CXCursor_TypedefDecl; case Decl::TypeAlias: return CXCursor_TypeAliasDecl; + case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl; case Decl::Var: return CXCursor_VarDecl; case Decl::Namespace: return CXCursor_Namespace; case Decl::NamespaceAlias: return CXCursor_NamespaceAlias; @@ -3376,7 +3374,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, case PCC_Statement: case PCC_RecoveryInFunction: if (S->getFnParent()) - AddPrettyFunctionResults(PP.getLangOpts(), Results); + AddPrettyFunctionResults(getLangOpts(), Results); break; case PCC_Namespace: @@ -3520,7 +3518,7 @@ void Sema::CodeCompleteExpression(Scope *S, if (S->getFnParent() && !Data.ObjCCollection && !Data.IntegralConstantExpression) - AddPrettyFunctionResults(PP.getLangOpts(), Results); + AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, false, PreferredTypeIsPointer); @@ -4051,7 +4049,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { // 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)) { + if (isCompleteType(Loc, NakedFn->getType())) { DeclarationName OpName = Context.DeclarationNames .getCXXOperatorName(OO_Call); LookupResult R(*this, OpName, Loc, LookupOrdinaryName); @@ -4093,7 +4091,7 @@ void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, return; // A complete type is needed to lookup for constructors. - if (RequireCompleteType(Loc, Type, 0)) + if (!isCompleteType(Loc, Type)) return; CXXRecordDecl *RD = Type->getAsCXXRecordDecl(); @@ -4205,7 +4203,7 @@ void Sema::CodeCompleteAfterIf(Scope *S) { Results.ExitScope(); if (S->getFnParent()) - AddPrettyFunctionResults(PP.getLangOpts(), Results); + AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, false); @@ -4912,7 +4910,7 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { Results.AddResult(CodeCompletionResult("atomic")); // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC. - if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC) + if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC) if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak)) Results.AddResult(CodeCompletionResult("weak")); @@ -5925,8 +5923,8 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, } } -void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, - unsigned NumProtocols) { +void Sema::CodeCompleteObjCProtocolReferences( + ArrayRef<IdentifierLocPair> Protocols) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); @@ -5937,9 +5935,9 @@ void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, // Tell the result set to ignore all of the protocols we have // already seen. // FIXME: This doesn't work when caching code-completion results. - for (unsigned I = 0; I != NumProtocols; ++I) - if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first, - Protocols[I].second)) + for (const IdentifierLocPair &Pair : Protocols) + if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, + Pair.second)) Results.Ignore(Protocol); // Add all protocols. @@ -7079,11 +7077,13 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, // If the result type was not already provided, add it to the // pattern as (type). - if (ReturnType.isNull()) - AddObjCPassingTypeChunk(Method->getSendResultType() - .stripObjCKindOfType(Context), + if (ReturnType.isNull()) { + QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context); + AttributedType::stripOuterNullability(ResTy); + AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context, Policy, Builder); + } Selector Sel = Method->getSelector(); @@ -7114,6 +7114,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, ParamType = (*P)->getOriginalType(); ParamType = ParamType.substObjCTypeArgs(Context, {}, ObjCSubstitutionContext::Parameter); + AttributedType::stripOuterNullability(ParamType); AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context, Policy, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp new file mode 100644 index 0000000..4b4fd6b --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp @@ -0,0 +1,448 @@ +//===--- SemaCoroutines.cpp - Semantic Analysis for Coroutines ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for C++ Coroutines. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/AST/Decl.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtCXX.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Overload.h" +using namespace clang; +using namespace sema; + +/// Look up the std::coroutine_traits<...>::promise_type for the given +/// function type. +static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType, + SourceLocation Loc) { + // FIXME: Cache std::coroutine_traits once we've found it. + NamespaceDecl *Std = S.getStdNamespace(); + if (!Std) { + S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found); + return QualType(); + } + + LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"), + Loc, Sema::LookupOrdinaryName); + if (!S.LookupQualifiedName(Result, Std)) { + S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found); + return QualType(); + } + + ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>(); + if (!CoroTraits) { + Result.suppressDiagnostics(); + // We found something weird. Complain about the first thing we found. + NamedDecl *Found = *Result.begin(); + S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); + return QualType(); + } + + // Form template argument list for coroutine_traits<R, P1, P2, ...>. + TemplateArgumentListInfo Args(Loc, Loc); + Args.addArgument(TemplateArgumentLoc( + TemplateArgument(FnType->getReturnType()), + S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), Loc))); + // FIXME: If the function is a non-static member function, add the type + // of the implicit object parameter before the formal parameters. + for (QualType T : FnType->getParamTypes()) + Args.addArgument(TemplateArgumentLoc( + TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, Loc))); + + // Build the template-id. + QualType CoroTrait = + S.CheckTemplateIdType(TemplateName(CoroTraits), Loc, Args); + if (CoroTrait.isNull()) + return QualType(); + if (S.RequireCompleteType(Loc, CoroTrait, + diag::err_coroutine_traits_missing_specialization)) + return QualType(); + + CXXRecordDecl *RD = CoroTrait->getAsCXXRecordDecl(); + assert(RD && "specialization of class template is not a class?"); + + // Look up the ::promise_type member. + LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), Loc, + Sema::LookupOrdinaryName); + S.LookupQualifiedName(R, RD); + auto *Promise = R.getAsSingle<TypeDecl>(); + if (!Promise) { + S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found) + << RD; + return QualType(); + } + + // The promise type is required to be a class type. + QualType PromiseType = S.Context.getTypeDeclType(Promise); + if (!PromiseType->getAsCXXRecordDecl()) { + // Use the fully-qualified name of the type. + auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, Std); + NNS = NestedNameSpecifier::Create(S.Context, NNS, false, + CoroTrait.getTypePtr()); + PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType); + + S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class) + << PromiseType; + return QualType(); + } + + return PromiseType; +} + +/// Check that this is a context in which a coroutine suspension can appear. +static FunctionScopeInfo * +checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) { + // 'co_await' and 'co_yield' are not permitted in unevaluated operands. + if (S.isUnevaluatedContext()) { + S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword; + return nullptr; + } + + // Any other usage must be within a function. + // FIXME: Reject a coroutine with a deduced return type. + auto *FD = dyn_cast<FunctionDecl>(S.CurContext); + if (!FD) { + S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext) + ? diag::err_coroutine_objc_method + : diag::err_coroutine_outside_function) << Keyword; + } else if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) { + // Coroutines TS [special]/6: + // A special member function shall not be a coroutine. + // + // FIXME: We assume that this really means that a coroutine cannot + // be a constructor or destructor. + S.Diag(Loc, diag::err_coroutine_ctor_dtor) + << isa<CXXDestructorDecl>(FD) << Keyword; + } else if (FD->isConstexpr()) { + S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword; + } else if (FD->isVariadic()) { + S.Diag(Loc, diag::err_coroutine_varargs) << Keyword; + } else { + auto *ScopeInfo = S.getCurFunction(); + assert(ScopeInfo && "missing function scope for function"); + + // If we don't have a promise variable, build one now. + if (!ScopeInfo->CoroutinePromise) { + QualType T = + FD->getType()->isDependentType() + ? S.Context.DependentTy + : lookupPromiseType(S, FD->getType()->castAs<FunctionProtoType>(), + Loc); + if (T.isNull()) + return nullptr; + + // Create and default-initialize the promise. + ScopeInfo->CoroutinePromise = + VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(), + &S.PP.getIdentifierTable().get("__promise"), T, + S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None); + S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise); + if (!ScopeInfo->CoroutinePromise->isInvalidDecl()) + S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false); + } + + return ScopeInfo; + } + + return nullptr; +} + +/// Build a call to 'operator co_await' if there is a suitable operator for +/// the given expression. +static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, + SourceLocation Loc, Expr *E) { + UnresolvedSet<16> Functions; + SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(), + Functions); + return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E); +} + +struct ReadySuspendResumeResult { + bool IsInvalid; + Expr *Results[3]; +}; + +static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, + StringRef Name, + MutableArrayRef<Expr *> Args) { + DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc); + + // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&. + CXXScopeSpec SS; + ExprResult Result = S.BuildMemberReferenceExpr( + Base, Base->getType(), Loc, /*IsPtr=*/false, SS, + SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr, + /*Scope=*/nullptr); + if (Result.isInvalid()) + return ExprError(); + + return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr); +} + +/// Build calls to await_ready, await_suspend, and await_resume for a co_await +/// expression. +static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc, + Expr *E) { + // Assume invalid until we see otherwise. + ReadySuspendResumeResult Calls = {true, {}}; + + const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"}; + for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) { + Expr *Operand = new (S.Context) OpaqueValueExpr( + Loc, E->getType(), VK_LValue, E->getObjectKind(), E); + + // FIXME: Pass coroutine handle to await_suspend. + ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None); + if (Result.isInvalid()) + return Calls; + Calls.Results[I] = Result.get(); + } + + Calls.IsInvalid = false; + return Calls; +} + +ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) { + if (E->getType()->isPlaceholderType()) { + ExprResult R = CheckPlaceholderExpr(E); + if (R.isInvalid()) return ExprError(); + E = R.get(); + } + + ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E); + if (Awaitable.isInvalid()) + return ExprError(); + return BuildCoawaitExpr(Loc, Awaitable.get()); +} +ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) { + auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await"); + if (!Coroutine) + return ExprError(); + + if (E->getType()->isPlaceholderType()) { + ExprResult R = CheckPlaceholderExpr(E); + if (R.isInvalid()) return ExprError(); + E = R.get(); + } + + if (E->getType()->isDependentType()) { + Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E); + Coroutine->CoroutineStmts.push_back(Res); + return Res; + } + + // If the expression is a temporary, materialize it as an lvalue so that we + // can use it multiple times. + if (E->getValueKind() == VK_RValue) + E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true); + + // Build the await_ready, await_suspend, await_resume calls. + ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E); + if (RSS.IsInvalid) + return ExprError(); + + Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1], + RSS.Results[2]); + Coroutine->CoroutineStmts.push_back(Res); + return Res; +} + +static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine, + SourceLocation Loc, StringRef Name, + MutableArrayRef<Expr *> Args) { + assert(Coroutine->CoroutinePromise && "no promise for coroutine"); + + // Form a reference to the promise. + auto *Promise = Coroutine->CoroutinePromise; + ExprResult PromiseRef = S.BuildDeclRefExpr( + Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc); + if (PromiseRef.isInvalid()) + return ExprError(); + + // Call 'yield_value', passing in E. + return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args); +} + +ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) { + auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield"); + if (!Coroutine) + return ExprError(); + + // Build yield_value call. + ExprResult Awaitable = + buildPromiseCall(*this, Coroutine, Loc, "yield_value", E); + if (Awaitable.isInvalid()) + return ExprError(); + + // Build 'operator co_await' call. + Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get()); + if (Awaitable.isInvalid()) + return ExprError(); + + return BuildCoyieldExpr(Loc, Awaitable.get()); +} +ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { + auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield"); + if (!Coroutine) + return ExprError(); + + if (E->getType()->isPlaceholderType()) { + ExprResult R = CheckPlaceholderExpr(E); + if (R.isInvalid()) return ExprError(); + E = R.get(); + } + + if (E->getType()->isDependentType()) { + Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E); + Coroutine->CoroutineStmts.push_back(Res); + return Res; + } + + // If the expression is a temporary, materialize it as an lvalue so that we + // can use it multiple times. + if (E->getValueKind() == VK_RValue) + E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true); + + // Build the await_ready, await_suspend, await_resume calls. + ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E); + if (RSS.IsInvalid) + return ExprError(); + + Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1], + RSS.Results[2]); + Coroutine->CoroutineStmts.push_back(Res); + return Res; +} + +StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) { + return BuildCoreturnStmt(Loc, E); +} +StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) { + auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return"); + if (!Coroutine) + return StmtError(); + + if (E && E->getType()->isPlaceholderType() && + !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) { + ExprResult R = CheckPlaceholderExpr(E); + if (R.isInvalid()) return StmtError(); + E = R.get(); + } + + // FIXME: If the operand is a reference to a variable that's about to go out + // of scope, we should treat the operand as an xvalue for this overload + // resolution. + ExprResult PC; + if (E && !E->getType()->isVoidType()) { + PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E); + } else { + E = MakeFullDiscardedValueExpr(E).get(); + PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None); + } + if (PC.isInvalid()) + return StmtError(); + + Expr *PCE = ActOnFinishFullExpr(PC.get()).get(); + + Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE); + Coroutine->CoroutineStmts.push_back(Res); + return Res; +} + +void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) { + FunctionScopeInfo *Fn = getCurFunction(); + assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine"); + + // Coroutines [stmt.return]p1: + // A return statement shall not appear in a coroutine. + if (Fn->FirstReturnLoc.isValid()) { + Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine); + auto *First = Fn->CoroutineStmts[0]; + Diag(First->getLocStart(), diag::note_declared_coroutine_here) + << (isa<CoawaitExpr>(First) ? 0 : + isa<CoyieldExpr>(First) ? 1 : 2); + } + + bool AnyCoawaits = false; + bool AnyCoyields = false; + for (auto *CoroutineStmt : Fn->CoroutineStmts) { + AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt); + AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt); + } + + if (!AnyCoawaits && !AnyCoyields) + Diag(Fn->CoroutineStmts.front()->getLocStart(), + diag::ext_coroutine_without_co_await_co_yield); + + SourceLocation Loc = FD->getLocation(); + + // Form a declaration statement for the promise declaration, so that AST + // visitors can more easily find it. + StmtResult PromiseStmt = + ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc); + if (PromiseStmt.isInvalid()) + return FD->setInvalidDecl(); + + // Form and check implicit 'co_await p.initial_suspend();' statement. + ExprResult InitialSuspend = + buildPromiseCall(*this, Fn, Loc, "initial_suspend", None); + // FIXME: Support operator co_await here. + if (!InitialSuspend.isInvalid()) + InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get()); + InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get()); + if (InitialSuspend.isInvalid()) + return FD->setInvalidDecl(); + + // Form and check implicit 'co_await p.final_suspend();' statement. + ExprResult FinalSuspend = + buildPromiseCall(*this, Fn, Loc, "final_suspend", None); + // FIXME: Support operator co_await here. + if (!FinalSuspend.isInvalid()) + FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get()); + FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get()); + if (FinalSuspend.isInvalid()) + return FD->setInvalidDecl(); + + // FIXME: Perform analysis of set_exception call. + + // FIXME: Try to form 'p.return_void();' expression statement to handle + // control flowing off the end of the coroutine. + + // Build implicit 'p.get_return_object()' expression and form initialization + // of return type from it. + ExprResult ReturnObject = + buildPromiseCall(*this, Fn, Loc, "get_return_object", None); + if (ReturnObject.isInvalid()) + return FD->setInvalidDecl(); + QualType RetType = FD->getReturnType(); + if (!RetType->isDependentType()) { + InitializedEntity Entity = + InitializedEntity::InitializeResult(Loc, RetType, false); + ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType, + ReturnObject.get()); + if (ReturnObject.isInvalid()) + return FD->setInvalidDecl(); + } + ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc); + if (ReturnObject.isInvalid()) + return FD->setInvalidDecl(); + + // FIXME: Perform move-initialization of parameters into frame-local copies. + SmallVector<Expr*, 16> ParamMoves; + + // Build body for the coroutine wrapper statement. + Body = new (Context) CoroutineBodyStmt( + Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(), + /*SetException*/nullptr, /*Fallthrough*/nullptr, + ReturnObject.get(), ParamMoves); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index c694a20..2c5516a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -33,7 +33,6 @@ #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering. #include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex #include "clang/Lex/Preprocessor.h" // Included for isCodeCompletionEnabled() -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" @@ -111,6 +110,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { case tok::kw_wchar_t: case tok::kw_bool: case tok::kw___underlying_type: + case tok::kw___auto_type: return true; case tok::annot_typename: @@ -795,7 +795,7 @@ Corrected: } // In C, we first see whether there is a tag type by the same name, in - // which case it's likely that the user just forget to write "enum", + // which case it's likely that the user just forgot to write "enum", // "struct", or "union". if (!getLangOpts().CPlusPlus && !SecondTry && isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { @@ -813,9 +813,8 @@ Corrected: unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; unsigned QualifiedDiag = diag::err_no_member_suggest; - NamedDecl *FirstDecl = Corrected.getCorrectionDecl(); - NamedDecl *UnderlyingFirstDecl - = FirstDecl? FirstDecl->getUnderlyingDecl() : nullptr; + NamedDecl *FirstDecl = Corrected.getFoundDecl(); + NamedDecl *UnderlyingFirstDecl = Corrected.getCorrectionDecl(); if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) { UnqualifiedDiag = diag::err_no_template_suggest; @@ -1022,7 +1021,7 @@ Corrected: if (FirstDecl->isCXXClassMember()) return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, - nullptr); + nullptr, S); bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); return BuildDeclarationNameExpr(SS, Result, ADL); @@ -1089,7 +1088,9 @@ Sema::SkippedDefinitionContext Sema::ActOnTagStartSkippedDefinition(Scope *S, auto Result = static_cast<SkippedDefinitionContext>(CurContext); CurContext = cast<TagDecl>(D)->getDefinition(); assert(CurContext && "skipping definition of undefined tag"); - S->setEntity(CurContext); + // Start lookups from the parent of the current context; we don't want to look + // into the pre-existing complete definition. + S->setEntity(CurContext->getLookupParent()); return Result; } @@ -1733,20 +1734,18 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, if (Error) { if (ForRedeclaration) Diag(Loc, diag::warn_implicit_decl_requires_sysheader) - << getHeaderName(Error) - << Context.BuiltinInfo.GetName(ID); + << getHeaderName(Error) << Context.BuiltinInfo.getName(ID); return nullptr; } if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(ID)) { Diag(Loc, diag::ext_implicit_lib_function_decl) - << Context.BuiltinInfo.GetName(ID) - << R; + << Context.BuiltinInfo.getName(ID) << R; if (Context.BuiltinInfo.getHeaderName(ID) && !Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc)) Diag(Loc, diag::note_include_header_or_declare) << Context.BuiltinInfo.getHeaderName(ID) - << Context.BuiltinInfo.GetName(ID); + << Context.BuiltinInfo.getName(ID); } DeclContext *Parent = Context.getTranslationUnitDecl(); @@ -1796,37 +1795,6 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, return New; } -/// \brief Filter out any previous declarations that the given declaration -/// 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(Sema &S, - NamedDecl *decl, - LookupResult &previous){ - // This is only interesting when modules are enabled. - if ((!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) || - !S.getLangOpts().ModulesHideInternalLinkage) - return; - - // Empty sets are uninteresting. - if (previous.empty()) - return; - - LookupResult::Filter filter = previous.makeFilter(); - while (filter.hasNext()) { - NamedDecl *old = filter.next(); - - // Non-hidden declarations are never ignored. - if (S.isVisible(old)) - continue; - - if (!old->isExternallyVisible()) - filter.erase(); - } - - filter.done(); -} - /// Typedef declarations don't have linkage, but they still denote the same /// entity if their types are the same. /// FIXME: This is notionally doing the same thing as ASTReaderDecl's @@ -1859,13 +1827,13 @@ static void filterNonConflictingPreviousTypedefDecls(Sema &S, // If both declarations give a tag declaration a typedef name for linkage // purposes, then they declare the same entity. - if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) && + if (S.getLangOpts().CPlusPlus && + OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) && Decl->getAnonDeclWithTypedefName()) continue; } - if (!Old->isExternallyVisible()) - Filter.erase(); + Filter.erase(); } Filter.done(); @@ -1910,7 +1878,8 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { /// how to resolve this situation, merging decls or emitting /// diagnostics as appropriate. If there was an error, set New to be invalid. /// -void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { +void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, + LookupResult &OldDecls) { // If the new decl is known invalid already, don't bother doing any // merging checks. if (New->isInvalidDecl()) return; @@ -1991,6 +1960,19 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { // Make the old tag definition visible. makeMergedDefinitionVisible(Hidden, NewTag->getLocation()); + + // If this was an unscoped enumeration, yank all of its enumerators + // out of the scope. + if (isa<EnumDecl>(NewTag)) { + Scope *EnumScope = getNonFieldDeclScope(S); + for (auto *D : NewTag->decls()) { + auto *ED = cast<EnumConstantDecl>(D); + assert(EnumScope->isDeclScope(ED)); + EnumScope->RemoveDecl(ED); + IdResolver.RemoveDecl(ED); + ED->getLexicalDeclContext()->removeDecl(ED); + } + } } } @@ -2206,14 +2188,15 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) { } static bool mergeDeclAttribute(Sema &S, NamedDecl *D, - const InheritableAttr *Attr, bool Override) { + const InheritableAttr *Attr, + Sema::AvailabilityMergeKind AMK) { InheritableAttr *NewAttr = nullptr; unsigned AttrSpellingListIndex = Attr->getSpellingListIndex(); if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr)) NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(), AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(), - AA->getMessage(), Override, + AA->getMessage(), AMK, AttrSpellingListIndex); else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr)) NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(), @@ -2246,11 +2229,22 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex); else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr)) NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex); + else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr)) + NewAttr = S.mergeInternalLinkageAttr( + D, InternalLinkageA->getRange(), + &S.Context.Idents.get(InternalLinkageA->getSpelling()), + AttrSpellingListIndex); + else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr)) + NewAttr = S.mergeCommonAttr(D, CommonA->getRange(), + &S.Context.Idents.get(CommonA->getSpelling()), + AttrSpellingListIndex); else if (isa<AlignedAttr>(Attr)) // AlignedAttrs are handled separately, because we need to handle all // such attributes on a declaration at the same time. NewAttr = nullptr; - else if (isa<DeprecatedAttr>(Attr) && Override) + else if ((isa<DeprecatedAttr>(Attr) || isa<UnavailableAttr>(Attr)) && + (AMK == Sema::AMK_Override || + AMK == Sema::AMK_ProtocolImplementation)) NewAttr = nullptr; else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr)) NewAttr = cast<InheritableAttr>(Attr->clone(S.Context)); @@ -2303,9 +2297,17 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { const Attr *NewAttribute = NewAttributes[I]; if (isa<AliasAttr>(NewAttribute)) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) - S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def)); - else { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) { + Sema::SkipBodyInfo SkipBody; + S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def), &SkipBody); + + // If we're skipping this definition, drop the "alias" attribute. + if (SkipBody.ShouldSkip) { + NewAttributes.erase(NewAttributes.begin() + I); + --E; + continue; + } + } else { VarDecl *VD = cast<VarDecl>(New); unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() == VarDecl::TentativeDefinition @@ -2376,9 +2378,24 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, if (!Old->hasAttrs() && !New->hasAttrs()) return; - // attributes declared post-definition are currently ignored + // Attributes declared post-definition are currently ignored. checkNewAttributesAfterDef(*this, New, Old); + if (AsmLabelAttr *NewA = New->getAttr<AsmLabelAttr>()) { + if (AsmLabelAttr *OldA = Old->getAttr<AsmLabelAttr>()) { + if (OldA->getLabel() != NewA->getLabel()) { + // This redeclaration changes __asm__ label. + Diag(New->getLocation(), diag::err_different_asm_label); + Diag(OldA->getLocation(), diag::note_previous_declaration); + } + } else if (Old->isUsed()) { + // This redeclaration adds an __asm__ label to a declaration that has + // already been ODR-used. + Diag(New->getLocation(), diag::err_late_asm_label_name) + << isa<FunctionDecl>(Old) << New->getAttr<AsmLabelAttr>()->getRange(); + } + } + if (!Old->hasAttrs()) return; @@ -2389,8 +2406,8 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, if (!foundAny) New->setAttrs(AttrVec()); for (auto *I : Old->specific_attrs<InheritableAttr>()) { - bool Override = false; // Ignore deprecated/unavailable/availability attributes if requested. + AvailabilityMergeKind LocalAMK = AMK_None; if (isa<DeprecatedAttr>(I) || isa<UnavailableAttr>(I) || isa<AvailabilityAttr>(I)) { @@ -2399,10 +2416,9 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, continue; case AMK_Redeclaration: - break; - case AMK_Override: - Override = true; + case AMK_ProtocolImplementation: + LocalAMK = AMK; break; } } @@ -2411,7 +2427,7 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, if (isa<UsedAttr>(I)) continue; - if (mergeDeclAttribute(*this, New, I, Override)) + if (mergeDeclAttribute(*this, New, I, LocalAMK)) foundAny = true; } @@ -2619,6 +2635,21 @@ static bool checkUsingShadowRedecl(Sema &S, UsingShadowDecl *OldS, return false; } +static bool hasIdenticalPassObjectSizeAttrs(const FunctionDecl *A, + const FunctionDecl *B) { + assert(A->getNumParams() == B->getNumParams()); + + auto AttrEq = [](const ParmVarDecl *A, const ParmVarDecl *B) { + const auto *AttrA = A->getAttr<PassObjectSizeAttr>(); + const auto *AttrB = B->getAttr<PassObjectSizeAttr>(); + if (AttrA == AttrB) + return true; + return AttrA && AttrB && AttrA->getType() == AttrB->getType(); + }; + + return std::equal(A->param_begin(), A->param_end(), B->param_begin(), AttrEq); +} + /// MergeFunctionDecl - We just parsed a function 'New' from /// declarator D which has the same name and scope as a previous /// declaration 'Old'. Figure out how to resolve this situation, @@ -2685,6 +2716,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, } } + if (New->hasAttr<InternalLinkageAttr>() && + !Old->hasAttr<InternalLinkageAttr>()) { + Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + New->dropAttr<InternalLinkageAttr>(); + } // If a function is first declared with a calling convention, but is later // declared or defined without one, all following decls assume the calling @@ -2790,7 +2828,17 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Old->isInlined() && !Old->hasAttr<GNUInlineAttr>()) { UndefinedButUsed.erase(Old->getCanonicalDecl()); } - + + // If pass_object_size params don't match up perfectly, this isn't a valid + // redeclaration. + if (Old->getNumParams() > 0 && Old->getNumParams() == New->getNumParams() && + !hasIdenticalPassObjectSizeAttrs(Old, New)) { + Diag(New->getLocation(), diag::err_different_pass_object_size_params) + << New->getDeclName(); + Diag(OldLocation, PrevDiag) << Old << Old->getType(); + return true; + } + if (getLangOpts().CPlusPlus) { // (C++98 13.1p2): // Certain function declarations cannot be overloaded: @@ -3115,7 +3163,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, // remain visible, a single bogus local redeclaration (which is // actually only a warning) could break all the downstream code. if (!New->getLexicalDeclContext()->isFunctionOrMethod()) - New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin); + New->getIdentifier()->revertBuiltin(); return false; } @@ -3179,8 +3227,11 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, // Merge the attributes, including deprecated/unavailable AvailabilityMergeKind MergeKind = - isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration - : AMK_Override; + isa<ObjCProtocolDecl>(oldMethod->getDeclContext()) + ? AMK_ProtocolImplementation + : isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration + : AMK_Override; + mergeDeclAttributes(newMethod, oldMethod, MergeKind); // Merge attributes from the parameters. @@ -3331,6 +3382,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { if (New->isInvalidDecl()) return; + if (!shouldLinkPossiblyHiddenDecl(Previous, New)) + return; + VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate(); // Verify the old decl was also a variable or variable template. @@ -3362,15 +3416,12 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { return New->setInvalidDecl(); } - if (!shouldLinkPossiblyHiddenDecl(Old, New)) - return; - // Ensure the template parameters are compatible. if (NewTemplate && !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), OldTemplate->getTemplateParameters(), /*Complain=*/true, TPL_TemplateMatch)) - return; + return New->setInvalidDecl(); // C++ [class.mem]p1: // A member shall not be declared twice in the member-specification [...] @@ -3395,6 +3446,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->dropAttr<WeakImportAttr>(); } + if (New->hasAttr<InternalLinkageAttr>() && + !Old->hasAttr<InternalLinkageAttr>()) { + Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + New->dropAttr<InternalLinkageAttr>(); + } + // Merge the types. VarDecl *MostRecent = Old->getMostRecentDecl(); if (MostRecent != Old) { @@ -3583,11 +3642,11 @@ void Sema::handleTagNumbering(const TagDecl *Tag, Scope *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()) + if (TagFromDeclSpec->isInvalidDecl()) return; - if (TagFromDeclSpec->getTypedefNameForAnonDecl()) + + // Do nothing if the tag already has a name for linkage purposes. + if (TagFromDeclSpec->hasNameForLinkage()) return; // A well-formed anonymous tag must always be a TUK_Definition. @@ -3595,8 +3654,11 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, // The type must match the tag exactly; no qualifiers allowed. if (!Context.hasSameType(NewTD->getUnderlyingType(), - Context.getTagDeclType(TagFromDeclSpec))) + Context.getTagDeclType(TagFromDeclSpec))) { + if (getLangOpts().CPlusPlus) + Context.addTypedefNameForUnnamedTagDecl(TagFromDeclSpec, NewTD); return; + } // If we've already computed linkage for the anonymous tag, then // adding a typedef name for the anonymous decl can change that @@ -3695,6 +3757,14 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return TagD; } + if (DS.isConceptSpecified()) { + // C++ Concepts TS [dcl.spec.concept]p1: A concept definition refers to + // either a function concept and its definition or a variable concept and + // its initializer. + Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); + return TagD; + } + DiagnoseFunctionSpecifiers(DS); if (DS.isFriendSpecified()) { @@ -3709,10 +3779,15 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, bool IsExplicitSpecialization = !TemplateParams.empty() && TemplateParams.back()->size() == 0; if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() && - !IsExplicitInstantiation && !IsExplicitSpecialization) { + !IsExplicitInstantiation && !IsExplicitSpecialization && + !isa<ClassTemplatePartialSpecializationDecl>(Tag)) { // Per C++ [dcl.type.elab]p1, a class declaration cannot have a // nested-name-specifier unless it is an explicit instantiation // or an explicit specialization. + // + // FIXME: We allow class template partial specializations here too, per the + // obvious intent of DR1819. + // // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either. Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier) << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange(); @@ -3882,7 +3957,7 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef, DeclContext *Owner, DeclarationName Name, SourceLocation NameLoc, - unsigned diagnostic) { + bool IsUnion) { LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName, Sema::ForRedeclaration); if (!SemaRef.LookupName(R, S)) return false; @@ -3897,7 +3972,8 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef, if (!SemaRef.isDeclInScope(PrevDecl, Owner, S)) return false; - SemaRef.Diag(NameLoc, diagnostic) << Name; + SemaRef.Diag(NameLoc, diag::err_anonymous_record_member_redecl) + << IsUnion << Name; SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration); return true; @@ -3925,10 +4001,6 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, AccessSpecifier AS, SmallVectorImpl<NamedDecl *> &Chaining, bool MSAnonStruct) { - unsigned diagKind - = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl - : diag::err_anonymous_struct_member_redecl; - bool Invalid = false; // Look every FieldDecl and IndirectFieldDecl with a name. @@ -3937,7 +4009,8 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, cast<NamedDecl>(D)->getDeclName()) { ValueDecl *VD = cast<ValueDecl>(D); if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(), - VD->getLocation(), diagKind)) { + VD->getLocation(), + AnonRecord->isUnion())) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be // distinct from the names of any other entity in the @@ -4131,7 +4204,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, assert(FD->getAccess() != AS_none); if (FD->getAccess() != AS_public) { Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member) - << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected); + << Record->isUnion() << (FD->getAccess() == AS_protected); Invalid = true; } @@ -4155,11 +4228,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Visual C++ allows type definition in anonymous struct or union. if (getLangOpts().MicrosoftExt) Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type) - << (int)Record->isUnion(); + << Record->isUnion(); else { // This is a nested type declaration. Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type) - << (int)Record->isUnion(); + << Record->isUnion(); Invalid = true; } } else { @@ -4168,7 +4241,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // not part of standard C++. Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_anonymous_type) - << (int)Record->isUnion(); + << Record->isUnion(); } } else if (isa<AccessSpecDecl>(Mem)) { // Any access specifier is fine. @@ -4189,10 +4262,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (getLangOpts().MicrosoftExt && DK == diag::err_anonymous_record_with_type) Diag(Mem->getLocation(), diag::ext_anonymous_record_with_type) - << (int)Record->isUnion(); + << Record->isUnion(); else { - Diag(Mem->getLocation(), DK) - << (int)Record->isUnion(); + Diag(Mem->getLocation(), DK) << Record->isUnion(); Invalid = true; } } @@ -4209,7 +4281,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (!Record->isUnion() && !Owner->isRecord()) { Diag(Record->getLocation(), diag::err_anonymous_struct_not_member) - << (int)getLangOpts().CPlusPlus; + << getLangOpts().CPlusPlus; Invalid = true; } @@ -4885,6 +4957,23 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, if (getLangOpts().CPlusPlus) CheckExtraCXXDefaultArguments(D); + if (D.getDeclSpec().isConceptSpecified()) { + // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be + // applied only to the definition of a function template or variable + // template, declared in namespace scope + if (!TemplateParamLists.size()) { + Diag(D.getDeclSpec().getConceptSpecLoc(), + diag:: err_concept_wrong_decl_kind); + return nullptr; + } + + if (!DC->getRedeclContext()->isFileContext()) { + Diag(D.getIdentifierLoc(), + diag::err_concept_decls_may_only_appear_in_namespace_scope); + return nullptr; + } + } + NamedDecl *New; bool AddToScope = true; @@ -5102,6 +5191,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getDeclSpec().isConstexprSpecified()) Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) << 1; + if (D.getDeclSpec().isConceptSpecified()) + Diag(D.getDeclSpec().getConceptSpecLoc(), + diag::err_concept_wrong_decl_kind); if (D.getName().Kind != UnqualifiedId::IK_Identifier) { Diag(D.getName().StartLocation, diag::err_typedef_not_identifier) @@ -5174,7 +5266,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, filterNonConflictingPreviousTypedefDecls(*this, NewTD, Previous); if (!Previous.empty()) { Redeclaration = true; - MergeTypedefNameDecl(NewTD, Previous); + MergeTypedefNameDecl(S, NewTD, Previous); } // If this is the C FILE type, notify the AST context. @@ -5343,14 +5435,26 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { } } - // dll attributes require external linkage. if (const InheritableAttr *Attr = getDLLAttr(&ND)) { - if (!ND.isExternallyVisible()) { + // dll attributes require external linkage. Static locals may have external + // linkage but still cannot be explicitly imported or exported. + auto *VD = dyn_cast<VarDecl>(&ND); + if (!ND.isExternallyVisible() || (VD && VD->isStaticLocal())) { S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern) << &ND << Attr; ND.setInvalidDecl(); } } + + // Virtual functions cannot be marked as 'notail'. + if (auto *Attr = ND.getAttr<NotTailCalledAttr>()) + if (auto *MD = dyn_cast<CXXMethodDecl>(&ND)) + if (MD->isVirtual()) { + S.Diag(ND.getLocation(), + diag::err_invalid_attribute_on_virtual_function) + << Attr; + ND.dropAttr<NotTailCalledAttr>(); + } } static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, @@ -5501,6 +5605,12 @@ static bool isIncompleteDeclExternC(Sema &S, const T *D) { // In C++, the overloadable attribute negates the effects of extern "C". if (!D->isInExternCContext() || D->template hasAttr<OverloadableAttr>()) return false; + + // So do CUDA's host/device attributes if overloading is enabled. + if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads && + (D->template hasAttr<CUDADeviceAttr>() || + D->template hasAttr<CUDAHostAttr>())) + return false; } return D->isExternC(); } @@ -5574,15 +5684,12 @@ bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) { return true; } -/// \brief Returns true if given declaration is TU-scoped and externally -/// visible. -static bool isDeclTUScopedExternallyVisible(const Decl *D) { - if (auto *FD = dyn_cast<FunctionDecl>(D)) - return (FD->getDeclContext()->isTranslationUnit() || FD->isExternC()) && - FD->hasExternalFormalLinkage(); - else if (auto *VD = dyn_cast<VarDecl>(D)) - return (VD->getDeclContext()->isTranslationUnit() || VD->isExternC()) && - VD->hasExternalFormalLinkage(); +/// \brief Returns true if given declaration has external C language linkage. +static bool isDeclExternC(const Decl *D) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->isExternC(); + if (const auto *VD = dyn_cast<VarDecl>(D)) + return VD->isExternC(); llvm_unreachable("Unknown type of decl!"); } @@ -5646,7 +5753,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Suppress the warning in system macros, it's used in macros in some // popular C system headers, such as in glibc's htonl() macro. Diag(D.getDeclSpec().getStorageClassSpecLoc(), - diag::warn_deprecated_register) + getLangOpts().CPlusPlus1z ? diag::ext_register_storage_class + : diag::warn_deprecated_register) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); } @@ -5670,12 +5778,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } if (getLangOpts().OpenCL) { - // Set up the special work-group-local storage class for variables in the - // OpenCL __local address space. - if (R.getAddressSpace() == LangAS::opencl_local) { - SC = SC_OpenCLWorkGroupLocal; - } - // OpenCL v1.2 s6.9.b p4: // The sampler type cannot be used with the __local and __global address // space qualifiers. @@ -5712,7 +5814,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, R, TInfo, SC); - + + if (D.getDeclSpec().containsPlaceholderType() && R->getContainedAutoType()) + ParsingInitForAutoVars.insert(NewVD); + if (D.isInvalidType()) NewVD->setInvalidDecl(); } else { @@ -5742,8 +5847,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, break; case SC_PrivateExtern: llvm_unreachable("C storage class in c++!"); - case SC_OpenCLWorkGroupLocal: - llvm_unreachable("OpenCL storage class in c++!"); } } @@ -5860,11 +5963,31 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, unsigned VDTemplateParamLists = TemplateParams ? 1 : 0; if (TemplateParamLists.size() > VDTemplateParamLists) NewVD->setTemplateParameterListsInfo( - Context, TemplateParamLists.size() - VDTemplateParamLists, - TemplateParamLists.data()); + Context, TemplateParamLists.drop_back(VDTemplateParamLists)); if (D.getDeclSpec().isConstexprSpecified()) NewVD->setConstexpr(true); + + if (D.getDeclSpec().isConceptSpecified()) { + NewVD->setConcept(true); + + // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not + // be declared with the thread_local, inline, friend, or constexpr + // specifiers, [...] + if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) { + Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 0 << 0; + NewVD->setInvalidDecl(true); + } + + if (D.getDeclSpec().isConstexprSpecified()) { + Diag(D.getDeclSpec().getConstexprSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 0 << 3; + NewVD->setInvalidDecl(true); + } + } } // Set the lexical context. If the declarator has a C++ scope specifier, the @@ -5990,19 +6113,31 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, break; case SC_Register: // Local Named register - if (!Context.getTargetInfo().isValidGCCRegisterName(Label)) + if (!Context.getTargetInfo().isValidGCCRegisterName(Label) && + DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; break; case SC_Static: case SC_Extern: case SC_PrivateExtern: - case SC_OpenCLWorkGroupLocal: break; } } else if (SC == SC_Register) { // Global Named register - if (!Context.getTargetInfo().isValidGCCRegisterName(Label)) - Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; + if (DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) { + const auto &TI = Context.getTargetInfo(); + bool HasSizeMismatch; + + if (!TI.isValidGCCRegisterName(Label)) + Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; + else if (!TI.validateGlobalRegisterVariable(Label, + Context.getTypeSize(R), + HasSizeMismatch)) + Diag(E->getExprLoc(), diag::err_asm_invalid_global_var_reg) << Label; + else if (HasSizeMismatch) + Diag(E->getExprLoc(), diag::err_asm_register_size_mismatch) << Label; + } + if (!R->isIntegralType(Context) && !R->isPointerType()) { Diag(D.getLocStart(), diag::err_asm_bad_register_type); NewVD->setInvalidDecl(true); @@ -6011,13 +6146,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, Label, 0)); - } else if (!ExtnameUndeclaredIdentifiers.empty() && - isDeclTUScopedExternallyVisible(NewVD)) { + } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I = ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier()); if (I != ExtnameUndeclaredIdentifiers.end()) { - NewVD->addAttr(I->second); - ExtnameUndeclaredIdentifiers.erase(I); + if (isDeclExternC(NewVD)) { + NewVD->addAttr(I->second); + ExtnameUndeclaredIdentifiers.erase(I); + } else + Diag(NewVD->getLocation(), diag::warn_redefine_extname_not_applied) + << /*Variable*/1 << NewVD; } } @@ -6118,6 +6256,22 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + // Special handling of variable named 'main'. + if (Name.isIdentifier() && Name.getAsIdentifierInfo()->isStr("main") && + NewVD->getDeclContext()->getRedeclContext()->isTranslationUnit() && + !getLangOpts().Freestanding && !NewVD->getDescribedVarTemplate()) { + + // C++ [basic.start.main]p3 + // A program that declares a variable main at global scope is ill-formed. + if (getLangOpts().CPlusPlus) + Diag(D.getLocStart(), diag::err_main_global_variable); + + // In C, and external-linkage variable named main results in undefined + // behavior. + else if (NewVD->hasExternalFormalLinkage()) + Diag(D.getLocStart(), diag::warn_main_redefined); + } + if (D.isRedeclaration() && !Previous.empty()) { checkDLLAttributeRedeclaration( *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD, @@ -6370,31 +6524,79 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { // This includes arrays of objects with address space qualifiers, but not // automatic variables that point to other address spaces. // ISO/IEC TR 18037 S5.1.2 - if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { + if (!getLangOpts().OpenCL + && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl); NewVD->setInvalidDecl(); return; } - // OpenCL v1.2 s6.5 - All program scope variables must be declared in the - // __constant address space. - if (getLangOpts().OpenCL && NewVD->isFileVarDecl() - && T.getAddressSpace() != LangAS::opencl_constant - && !T->isSamplerT()){ - Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space); - NewVD->setInvalidDecl(); - return; - } - // OpenCL v1.2 s6.8 -- The static qualifier is valid only in program // scope. - if ((getLangOpts().OpenCLVersion >= 120) - && NewVD->isStaticLocal()) { + if (getLangOpts().OpenCLVersion == 120 && + !getOpenCLOptions().cl_clang_storage_class_specifiers && + NewVD->isStaticLocal()) { Diag(NewVD->getLocation(), diag::err_static_function_scope); NewVD->setInvalidDecl(); return; } + // OpenCL v1.2 s6.5 - All program scope variables must be declared in the + // __constant address space. + // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static + // variables inside a function can also be declared in the global + // address space. + if (getLangOpts().OpenCL) { + if (NewVD->isFileVarDecl()) { + if (!T->isSamplerT() && + !(T.getAddressSpace() == LangAS::opencl_constant || + (T.getAddressSpace() == LangAS::opencl_global && + getLangOpts().OpenCLVersion == 200))) { + if (getLangOpts().OpenCLVersion == 200) + Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) + << "global or constant"; + else + Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) + << "constant"; + NewVD->setInvalidDecl(); + return; + } + } else { + // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static + // variables inside a function can also be declared in the global + // address space. + if (NewVD->isStaticLocal() && + !(T.getAddressSpace() == LangAS::opencl_constant || + (T.getAddressSpace() == LangAS::opencl_global && + getLangOpts().OpenCLVersion == 200))) { + if (getLangOpts().OpenCLVersion == 200) + Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) + << "global or constant"; + else + Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) + << "constant"; + NewVD->setInvalidDecl(); + return; + } + // OpenCL v1.1 s6.5.2 and s6.5.3 no local or constant variables + // in functions. + if (T.getAddressSpace() == LangAS::opencl_constant || + T.getAddressSpace() == LangAS::opencl_local) { + FunctionDecl *FD = getCurFunctionDecl(); + if (FD && !FD->hasAttr<OpenCLKernelAttr>()) { + if (T.getAddressSpace() == LangAS::opencl_constant) + Diag(NewVD->getLocation(), diag::err_opencl_non_kernel_variable) + << "constant"; + else + Diag(NewVD->getLocation(), diag::err_opencl_non_kernel_variable) + << "local"; + NewVD->setInvalidDecl(); + return; + } + } + } + } + if (NewVD->hasLocalStorage() && T.isObjCGCWeak() && !NewVD->hasAttr<BlocksAttr>()) { if (getLangOpts().getGC() != LangOptions::NonGC) @@ -6506,9 +6708,6 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { checkForConflictWithNonVisibleExternC(*this, NewVD, Previous)) Previous.setShadowed(); - // Filter out any non-conflicting previous declarations. - filterNonConflictingPreviousDecls(*this, NewVD, Previous); - if (!Previous.empty()) { MergeVarDecl(NewVD, Previous); return true; @@ -6516,50 +6715,45 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { return false; } -/// \brief Data used with FindOverriddenMethod -struct FindOverriddenMethodData { +namespace { +struct FindOverriddenMethod { Sema *S; CXXMethodDecl *Method; -}; -/// \brief Member lookup function that determines whether a given C++ -/// method overrides a method in a base class, to be used with -/// CXXRecordDecl::lookupInBases(). -static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - void *UserData) { - RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); + /// Member lookup function that determines whether a given C++ + /// method overrides a method in a base class, to be used with + /// CXXRecordDecl::lookupInBases(). + bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + RecordDecl *BaseRecord = + Specifier->getType()->getAs<RecordType>()->getDecl(); - FindOverriddenMethodData *Data - = reinterpret_cast<FindOverriddenMethodData*>(UserData); - - DeclarationName Name = Data->Method->getDeclName(); - - // FIXME: Do we care about other names here too? - if (Name.getNameKind() == DeclarationName::CXXDestructorName) { - // We really want to find the base class destructor here. - QualType T = Data->S->Context.getTypeDeclType(BaseRecord); - CanQualType CT = Data->S->Context.getCanonicalType(T); - - Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT); - } - - for (Path.Decls = BaseRecord->lookup(Name); - !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - NamedDecl *D = Path.Decls.front(); - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false)) - return true; + DeclarationName Name = Method->getDeclName(); + + // FIXME: Do we care about other names here too? + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + // We really want to find the base class destructor here. + QualType T = S->Context.getTypeDeclType(BaseRecord); + CanQualType CT = S->Context.getCanonicalType(T); + + Name = S->Context.DeclarationNames.getCXXDestructorName(CT); } + + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + NamedDecl *D = Path.Decls.front(); + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + if (MD->isVirtual() && !S->IsOverload(Method, MD, false)) + return true; + } + } + + return false; } - - return false; -} +}; + +enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted }; +} // end anonymous namespace -namespace { - enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted }; -} /// \brief Report an error regarding overriding, along with any relevant /// overriden methods. /// @@ -6587,13 +6781,13 @@ static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD, bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { // Look for methods in base classes that this method might override. CXXBasePaths Paths; - FindOverriddenMethodData Data; - Data.Method = MD; - Data.S = this; + FindOverriddenMethod FOM; + FOM.Method = MD; + FOM.S = this; bool hasDeletedOverridenMethods = false; bool hasNonDeletedOverridenMethods = false; bool AddedAny = false; - if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) { + if (DC->lookupInBases(FOM, Paths)) { for (auto *I : Paths.found_decls()) { if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) { MD->addOverriddenMethod(OldMD->getCanonicalDecl()); @@ -7200,7 +7394,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << DeclSpec::getSpecifierName(TSCS); if (D.isFirstDeclarationOfMember()) - adjustMemberFunctionCC(R, D.isStaticMember()); + adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(), + D.getIdentifierLoc()); bool isFriend = false; FunctionTemplateDecl *FunctionTemplate = nullptr; @@ -7236,6 +7431,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isVirtual = D.getDeclSpec().isVirtualSpecified(); bool isExplicit = D.getDeclSpec().isExplicitSpecified(); bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); + bool isConcept = D.getDeclSpec().isConceptSpecified(); isFriend = D.getDeclSpec().isFriendSpecified(); if (isFriend && !isInline && D.isFunctionDefinition()) { // C++ [class.friend]p5 @@ -7309,17 +7505,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // For source fidelity, store the other template param lists. if (TemplateParamLists.size() > 1) { NewFD->setTemplateParameterListsInfo(Context, - TemplateParamLists.size() - 1, - TemplateParamLists.data()); + TemplateParamLists.drop_back(1)); } } else { // This is a function template specialization. isFunctionTemplateSpecialization = true; // For source fidelity, store all the template param lists. if (TemplateParamLists.size() > 0) - NewFD->setTemplateParameterListsInfo(Context, - TemplateParamLists.size(), - TemplateParamLists.data()); + NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists); // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". if (isFriend) { @@ -7349,9 +7542,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // this is NOT (an explicit specialization of) a template. if (TemplateParamLists.size() > 0) // For source fidelity, store all the template param lists. - NewFD->setTemplateParameterListsInfo(Context, - TemplateParamLists.size(), - TemplateParamLists.data()); + NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists); } if (Invalid) { @@ -7452,6 +7643,67 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor); } + if (isConcept) { + // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be + // applied only to the definition of a function template [...] + if (!D.isFunctionDefinition()) { + Diag(D.getDeclSpec().getConceptSpecLoc(), + diag::err_function_concept_not_defined); + NewFD->setInvalidDecl(); + } + + // C++ Concepts TS [dcl.spec.concept]p1: [...] A function concept shall + // have no exception-specification and is treated as if it were specified + // with noexcept(true) (15.4). [...] + if (const FunctionProtoType *FPT = R->getAs<FunctionProtoType>()) { + if (FPT->hasExceptionSpec()) { + SourceRange Range; + if (D.isFunctionDeclarator()) + Range = D.getFunctionTypeInfo().getExceptionSpecRange(); + Diag(NewFD->getLocation(), diag::err_function_concept_exception_spec) + << FixItHint::CreateRemoval(Range); + NewFD->setInvalidDecl(); + } else { + Context.adjustExceptionSpec(NewFD, EST_BasicNoexcept); + } + + // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the + // following restrictions: + // - The declaration's parameter list shall be equivalent to an empty + // parameter list. + if (FPT->getNumParams() > 0 || FPT->isVariadic()) + Diag(NewFD->getLocation(), diag::err_function_concept_with_params); + } + + // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is + // implicity defined to be a constexpr declaration (implicitly inline) + NewFD->setImplicitlyInline(); + + // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not + // be declared with the thread_local, inline, friend, or constexpr + // specifiers, [...] + if (isInline) { + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 1; + NewFD->setInvalidDecl(true); + } + + if (isFriend) { + Diag(D.getDeclSpec().getFriendSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 2; + NewFD->setInvalidDecl(true); + } + + if (isConstexpr) { + Diag(D.getDeclSpec().getConstexprSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 3; + NewFD->setInvalidDecl(true); + } + } + // If __module_private__ was specified, mark the function accordingly. if (D.getDeclSpec().isModulePrivateSpecified()) { if (isFunctionTemplateSpecialization) { @@ -7539,13 +7791,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, StringLiteral *SE = cast<StringLiteral>(E); NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, SE->getString(), 0)); - } else if (!ExtnameUndeclaredIdentifiers.empty() && - isDeclTUScopedExternallyVisible(NewFD)) { + } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I = ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier()); if (I != ExtnameUndeclaredIdentifiers.end()) { - NewFD->addAttr(I->second); - ExtnameUndeclaredIdentifiers.erase(I); + if (isDeclExternC(NewFD)) { + NewFD->addAttr(I->second); + ExtnameUndeclaredIdentifiers.erase(I); + } else + Diag(NewFD->getLocation(), diag::warn_redefine_extname_not_applied) + << /*Variable*/0 << NewFD; } } @@ -8061,9 +8316,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, bool MergeTypeWithPrevious = !getLangOpts().CPlusPlus && !Previous.isShadowed(); - // Filter out any non-conflicting previous declarations. - filterNonConflictingPreviousDecls(*this, NewFD, Previous); - bool Redeclaration = false; NamedDecl *OldDecl = nullptr; @@ -8075,7 +8327,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // there's no more work to do here; we'll just add the new // function to the scope. if (!AllowOverloadingOfFunction(Previous, Context)) { - NamedDecl *Candidate = Previous.getFoundDecl(); + NamedDecl *Candidate = Previous.getRepresentativeDecl(); if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) { Redeclaration = true; OldDecl = Candidate; @@ -8117,7 +8369,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // Check for a previous extern "C" declaration with this name. if (!Redeclaration && checkForConflictWithNonVisibleExternC(*this, 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... @@ -8294,7 +8545,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) { // The type of this function differs from the type of the builtin, // so forget about the builtin entirely. - Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents); + Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents); } } @@ -8577,9 +8828,8 @@ namespace { // Convert FieldDecls to their index number. llvm::SmallVector<unsigned, 4> UsedFieldIndex; - for (auto I = Fields.rbegin(), E = Fields.rend(); I != E; ++I) { - UsedFieldIndex.push_back((*I)->getFieldIndex()); - } + for (const FieldDecl *I : llvm::reverse(Fields)) + UsedFieldIndex.push_back(I->getFieldIndex()); // See if a warning is needed by checking the first difference in index // numbers. If field being used has index less than the field being @@ -8832,6 +9082,96 @@ namespace { } } +QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, + DeclarationName Name, QualType Type, + TypeSourceInfo *TSI, + SourceRange Range, bool DirectInit, + Expr *Init) { + bool IsInitCapture = !VDecl; + assert((!VDecl || !VDecl->isInitCapture()) && + "init captures are expected to be deduced prior to initialization"); + + ArrayRef<Expr *> DeduceInits = Init; + if (DirectInit) { + if (auto *PL = dyn_cast<ParenListExpr>(Init)) + DeduceInits = PL->exprs(); + else if (auto *IL = dyn_cast<InitListExpr>(Init)) + DeduceInits = IL->inits(); + } + + // Deduction only works if we have exactly one source expression. + if (DeduceInits.empty()) { + // It isn't possible to write this directly, but it is possible to + // end up in this situation with "auto x(some_pack...);" + Diag(Init->getLocStart(), IsInitCapture + ? diag::err_init_capture_no_expression + : diag::err_auto_var_init_no_expression) + << Name << Type << Range; + return QualType(); + } + + if (DeduceInits.size() > 1) { + Diag(DeduceInits[1]->getLocStart(), + IsInitCapture ? diag::err_init_capture_multiple_expressions + : diag::err_auto_var_init_multiple_expressions) + << Name << Type << Range; + return QualType(); + } + + Expr *DeduceInit = DeduceInits[0]; + if (DirectInit && isa<InitListExpr>(DeduceInit)) { + Diag(Init->getLocStart(), IsInitCapture + ? diag::err_init_capture_paren_braces + : diag::err_auto_var_init_paren_braces) + << isa<InitListExpr>(Init) << Name << Type << Range; + return QualType(); + } + + // Expressions default to 'id' when we're in a debugger. + bool DefaultedAnyToId = false; + if (getLangOpts().DebuggerCastResultToId && + Init->getType() == Context.UnknownAnyTy && !IsInitCapture) { + ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); + if (Result.isInvalid()) { + return QualType(); + } + Init = Result.get(); + DefaultedAnyToId = true; + } + + QualType DeducedType; + if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) { + if (!IsInitCapture) + DiagnoseAutoDeductionFailure(VDecl, DeduceInit); + else if (isa<InitListExpr>(Init)) + Diag(Range.getBegin(), + diag::err_init_capture_deduction_failure_from_init_list) + << Name + << (DeduceInit->getType().isNull() ? TSI->getType() + : DeduceInit->getType()) + << DeduceInit->getSourceRange(); + else + Diag(Range.getBegin(), diag::err_init_capture_deduction_failure) + << Name << TSI->getType() + << (DeduceInit->getType().isNull() ? TSI->getType() + : DeduceInit->getType()) + << DeduceInit->getSourceRange(); + } + + // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using + // 'id' instead of a specific object type prevents most of our usual + // checks. + // We only want to warn outside of template instantiations, though: + // inside a template, the 'id' could have come from a parameter. + if (ActiveTemplateInstantiations.empty() && !DefaultedAnyToId && + !IsInitCapture && !DeducedType.isNull() && DeducedType->isObjCIdType()) { + SourceLocation Loc = TSI->getTypeLoc().getBeginLoc(); + Diag(Loc, diag::warn_auto_var_is_id) << Name << Range; + } + + return DeducedType; +} + /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. @@ -8859,79 +9199,27 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, RealDecl->setInvalidDecl(); return; } - ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(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 + // 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; } + Init = Res.get(); - 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. - if (CXXDirectInit) { - if (CXXDirectInit->getNumExprs() == 0) { - // It isn't possible to write this directly, but it is possible to - // end up in this situation with "auto x(some_pack...);" - Diag(CXXDirectInit->getLocStart(), - VDecl->isInitCapture() ? diag::err_init_capture_no_expression - : diag::err_auto_var_init_no_expression) - << VDecl->getDeclName() << VDecl->getType() - << VDecl->getSourceRange(); - RealDecl->setInvalidDecl(); - return; - } else if (CXXDirectInit->getNumExprs() > 1) { - Diag(CXXDirectInit->getExpr(1)->getLocStart(), - VDecl->isInitCapture() - ? diag::err_init_capture_multiple_expressions - : diag::err_auto_var_init_multiple_expressions) - << VDecl->getDeclName() << VDecl->getType() - << VDecl->getSourceRange(); - RealDecl->setInvalidDecl(); - return; - } else { - DeduceInit = CXXDirectInit->getExpr(0); - if (isa<InitListExpr>(DeduceInit)) - Diag(CXXDirectInit->getLocStart(), - diag::err_auto_var_init_paren_braces) - << VDecl->getDeclName() << VDecl->getType() - << VDecl->getSourceRange(); - } - } - - // Expressions default to 'id' when we're in a debugger. - bool DefaultedToAuto = false; - if (getLangOpts().DebuggerCastResultToId && - Init->getType() == Context.UnknownAnyTy) { - ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); - if (Result.isInvalid()) { - VDecl->setInvalidDecl(); - return; - } - Init = Result.get(); - DefaultedToAuto = true; - } - - QualType DeducedType; - if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) == - DAR_Failed) - DiagnoseAutoDeductionFailure(VDecl, DeduceInit); + QualType DeducedType = deduceVarTypeFromInitializer( + VDecl, VDecl->getDeclName(), VDecl->getType(), + VDecl->getTypeSourceInfo(), VDecl->getSourceRange(), DirectInit, Init); if (DeducedType.isNull()) { RealDecl->setInvalidDecl(); return; } + VDecl->setType(DeducedType); assert(VDecl->isLinkageValid()); @@ -8939,38 +9227,18 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) VDecl->setInvalidDecl(); - // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using - // 'id' instead of a specific object type prevents most of our usual checks. - // We only want to warn outside of template instantiations, though: - // inside a template, the 'id' could have come from a parameter. - if (ActiveTemplateInstantiations.empty() && !DefaultedToAuto && - DeducedType->isObjCIdType()) { - SourceLocation Loc = - VDecl->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); - Diag(Loc, diag::warn_auto_var_is_id) - << VDecl->getDeclName() << DeduceInit->getSourceRange(); - } - // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. if (VarDecl *Old = VDecl->getPreviousDecl()) { // We never need to merge the type, because we cannot form an incomplete // array of auto, nor deduce such a type. - MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/false); + MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/ false); } // Check the deduced type is valid for a variable declaration. CheckVariableDeclarationType(VDecl); if (VDecl->isInvalidDecl()) return; - - // If all looks well, warn if this is a case that will change meaning when - // we implement N3922. - if (DirectInit && !CXXDirectInit && isa<InitListExpr>(Init)) { - Diag(Init->getLocStart(), - diag::warn_auto_var_direct_list_init) - << FixItHint::CreateInsertion(Init->getLocStart(), "="); - } } // dllimport cannot be used on variable definitions. @@ -9059,7 +9327,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // OpenCL 1.1 6.5.2: "Variables allocated in the __local address space inside // a kernel function cannot be initialized." - if (VDecl->getStorageClass() == SC_OpenCLWorkGroupLocal) { + if (VDecl->getType().getAddressSpace() == LangAS::opencl_local) { Diag(VDecl->getLocation(), diag::err_local_cant_init); VDecl->setInvalidDecl(); return; @@ -9082,17 +9350,18 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } // Perform the initialization. + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); if (!VDecl->isInvalidDecl()) { InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); - InitializationKind Kind - = DirectInit ? - CXXDirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(), - Init->getLocStart(), - Init->getLocEnd()) - : InitializationKind::CreateDirectList( - VDecl->getLocation()) - : InitializationKind::CreateCopy(VDecl->getLocation(), - Init->getLocStart()); + InitializationKind Kind = + DirectInit + ? CXXDirectInit + ? InitializationKind::CreateDirect(VDecl->getLocation(), + Init->getLocStart(), + Init->getLocEnd()) + : InitializationKind::CreateDirectList(VDecl->getLocation()) + : InitializationKind::CreateCopy(VDecl->getLocation(), + Init->getLocStart()); MultiExprArg Args = Init; if (CXXDirectInit) @@ -9156,7 +9425,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Init->getLocStart())) - getCurFunction()->markSafeWeakUse(Init); + getCurFunction()->markSafeWeakUse(Init); } // The initialization is usually a full-expression. @@ -9409,6 +9678,15 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, return; } + // C++ Concepts TS [dcl.spec.concept]p1: [...] A variable template + // definition having the concept specifier is called a variable concept. A + // concept definition refers to [...] a variable concept and its initializer. + if (Var->isConcept()) { + Diag(Var->getLocation(), diag::err_var_concept_not_initialized); + Var->setInvalidDecl(); + return; + } + // OpenCL v1.1 s6.5.3: variables declared in the constant address space must // be initialized. if (!Var->isInvalidDecl() && @@ -9621,8 +9899,6 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) { case SC_Register: Error = 4; break; - case SC_OpenCLWorkGroupLocal: - llvm_unreachable("Unexpected storage class"); } if (Error != -1) { Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) @@ -9665,9 +9941,9 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isInvalidDecl()) return; - // In ARC, don't allow jumps past the implicit initialization of a + // In Objective-C, don't allow jumps past the implicit initialization of a // local retaining variable. - if (getLangOpts().ObjCAutoRefCount && + if (getLangOpts().ObjC1 && var->hasLocalStorage()) { switch (var->getType().getObjCLifetime()) { case Qualifiers::OCL_None: @@ -9913,9 +10189,17 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { // dllimport/dllexport variables cannot be thread local, their TLS index // isn't exported with the variable. if (DLLAttr && VD->getTLSKind()) { - Diag(VD->getLocation(), diag::err_attribute_dll_thread_local) << VD - << DLLAttr; - VD->setInvalidDecl(); + auto *F = dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod()); + if (F && getDLLAttr(F)) { + assert(VD->isStaticLocal()); + // But if this is a static local in a dlimport/dllexport function, the + // function will never be inlined, which means the var would never be + // imported, so having it marked import/export is safe. + } else { + Diag(VD->getLocation(), diag::err_attribute_dll_thread_local) << VD + << DLLAttr; + VD->setInvalidDecl(); + } } if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) { @@ -9988,8 +10272,9 @@ 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(Tag, S); - if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl()) - Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup); + if (FirstDeclaratorInGroup && !Tag->hasNameForLinkage() && + getLangOpts().CPlusPlus) + Context.addDeclaratorForUnnamedTagDecl(Tag, FirstDeclaratorInGroup); } } @@ -10028,7 +10313,7 @@ Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group, } else if (DeducedCanon != UCanon) { Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), diag::err_auto_different_deductions) - << (AT->isDecltypeAuto() ? 1 : 0) + << (unsigned)AT->getKeyword() << Deduced << DeducedDecl->getDeclName() << U << D->getDeclName() << DeducedDecl->getInit()->getSourceRange() @@ -10118,6 +10403,8 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (DS.isConstexprSpecified()) Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr) << 0; + if (DS.isConceptSpecified()) + Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); DiagnoseFunctionSpecifiers(DS); @@ -10370,14 +10657,17 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, } } -Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { +Decl * +Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + SkipBodyInfo *SkipBody) { assert(getCurFunctionDecl() == nullptr && "Function parsing confused"); assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); D.setFunctionDefinitionKind(FDK_Definition); - Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg()); - return ActOnStartOfFunctionDef(FnBodyScope, DP); + Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists); + return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody); } void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) { @@ -10441,7 +10731,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, void Sema::CheckForFunctionRedefinition(FunctionDecl *FD, - const FunctionDecl *EffectiveDefinition) { + const FunctionDecl *EffectiveDefinition, + SkipBodyInfo *SkipBody) { // Don't complain if we're in GNU89 mode and the previous definition // was an extern inline function. const FunctionDecl *Definition = EffectiveDefinition; @@ -10453,17 +10744,20 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, 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) && + // a template, skip the new definition. + if (SkipBody && !hasVisibleDefinition(Definition) && (Definition->getFormalLinkage() == InternalLinkage || Definition->isInlined() || Definition->getDescribedFunctionTemplate() || - Definition->getNumTemplateParameterLists())) + Definition->getNumTemplateParameterLists())) { + SkipBody->ShouldSkip = true; + if (auto *TD = Definition->getDescribedFunctionTemplate()) + makeMergedDefinitionVisible(TD, FD->getLocation()); + else + makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition), + FD->getLocation()); return; + } if (getLangOpts().GNUMode && Definition->isInlineSpecified() && Definition->getStorageClass() == SC_Extern) @@ -10524,7 +10818,8 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, } } -Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { +Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, + SkipBodyInfo *SkipBody) { // Clear the last template instantiation error context. LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); @@ -10536,6 +10831,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { FD = FunTmpl->getTemplatedDecl(); else FD = cast<FunctionDecl>(D); + + // See if this is a redefinition. + if (!FD->isLateTemplateParsed()) { + CheckForFunctionRedefinition(FD, nullptr, SkipBody); + + // If we're skipping the body, we're done. Don't enter the scope. + if (SkipBody && SkipBody->ShouldSkip) + return D; + } + // If we are instantiating a generic lambda call operator, push // a LambdaScopeInfo onto the function stack. But use the information // that's already been calculated (ActOnLambdaExpr) to prime the current @@ -10555,10 +10860,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // Enter a new function scope PushFunctionScope(); - // See if this is a redefinition. - if (!FD->isLateTemplateParsed()) - CheckForFunctionRedefinition(FD); - // Builtin functions cannot be defined. if (unsigned BuiltinID = FD->getBuiltinID()) { if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) && @@ -10734,6 +11035,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr; + if (getLangOpts().Coroutines && !getCurFunction()->CoroutineStmts.empty()) + CheckCompletedCoroutineBody(FD, Body); + if (FD) { FD->setBody(Body); @@ -11073,7 +11377,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, - /*ESpecLoc=*/NoLoc, + /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, @@ -11159,6 +11463,18 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation())); if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->hasAttr<ConstAttr>()) FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation())); + if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads && + Context.BuiltinInfo.isTSBuiltin(BuiltinID) && + !FD->hasAttr<CUDADeviceAttr>() && !FD->hasAttr<CUDAHostAttr>()) { + // Assign appropriate attribute depending on CUDA compilation + // mode and the target builtin belongs to. E.g. during host + // compilation, aux builtins are __device__, the rest are __host__. + if (getLangOpts().CUDAIsDevice != + Context.BuiltinInfo.isAuxBuiltinID(BuiltinID)) + FD->addAttr(CUDADeviceAttr::CreateImplicit(Context, FD->getLocation())); + else + FD->addAttr(CUDAHostAttr::CreateImplicit(Context, FD->getLocation())); + } } IdentifierInfo *Name = FD->getIdentifier(); @@ -11269,9 +11585,9 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { /// Check whether this is a valid redeclaration of a previous enumeration. /// \return true if the redeclaration was invalid. -bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, - QualType EnumUnderlyingTy, - const EnumDecl *Prev) { +bool Sema::CheckEnumRedeclaration( + SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy, + bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) { bool IsFixed = !EnumUnderlyingTy.isNull(); if (IsScoped != Prev->isScoped()) { @@ -11293,6 +11609,10 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, << Prev->getIntegerTypeRange(); return true; } + } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) { + ; + } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) { + ; } else if (IsFixed != Prev->isFixed()) { Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch) << Prev->isFixed(); @@ -11459,7 +11779,6 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S, std::reverse(Namespaces.begin(), Namespaces.end()); for (auto *II : Namespaces) OS << II->getName() << "::"; - OS.flush(); return FixItHint::CreateInsertion(NameLoc, Insertion); } @@ -11563,6 +11882,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // this early, because it's needed to detect if this is an incompatible // redeclaration. llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying; + bool EnumUnderlyingIsImplicit = false; if (Kind == TTK_Enum) { if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) @@ -11584,9 +11904,13 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, UPPC_FixedUnderlyingType)) EnumUnderlying = Context.IntTy.getTypePtr(); - } else if (getLangOpts().MSVCCompat) - // Microsoft enums are always of int type. - EnumUnderlying = Context.IntTy.getTypePtr(); + } else if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + if (getLangOpts().MSVCCompat || TUK == TUK_Definition) { + // Microsoft enums are always of int type. + EnumUnderlying = Context.IntTy.getTypePtr(); + EnumUnderlyingIsImplicit = true; + } + } } DeclContext *SearchDC = CurContext; @@ -11816,9 +12140,16 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // In C++, we need to do a redeclaration lookup to properly // diagnose some problems. + // FIXME: redeclaration lookup is also used (with and without C++) to find a + // hidden declaration so that we don't get ambiguity errors when using a + // type declared by an elaborated-type-specifier. In C that is not correct + // and we should instead merge compatible types found by lookup. if (getLangOpts().CPlusPlus) { Previous.setRedeclarationKind(ForRedeclaration); LookupQualifiedName(Previous, SearchDC); + } else { + Previous.setRedeclarationKind(ForRedeclaration); + LookupName(Previous, S); } } @@ -11932,7 +12263,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // returning the previous declaration, unless this is a definition, // in which case we want the caller to bail out. if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc, - ScopedEnum, EnumUnderlyingTy, PrevEnum)) + ScopedEnum, EnumUnderlyingTy, + EnumUnderlyingIsImplicit, PrevEnum)) return TUK == TUK_Declaration ? PrevTagDecl : nullptr; } @@ -12203,9 +12535,7 @@ CreateNewDecl: New->setQualifierInfo(SS.getWithLocInContext(Context)); if (TemplateParameterLists.size() > 0) { - New->setTemplateParameterListsInfo(Context, - TemplateParameterLists.size(), - TemplateParameterLists.data()); + New->setTemplateParameterListsInfo(Context, TemplateParameterLists); } } else @@ -12504,26 +12834,41 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, } if (!FieldTy->isDependentType()) { - uint64_t TypeSize = Context.getTypeSize(FieldTy); - if (Value.getZExtValue() > TypeSize) { - if (!getLangOpts().CPlusPlus || IsMsStruct || - Context.getTargetInfo().getCXXABI().isMicrosoft()) { - if (FieldName) - return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) - << FieldName << (unsigned)Value.getZExtValue() - << (unsigned)TypeSize; - - return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size) - << (unsigned)Value.getZExtValue() << (unsigned)TypeSize; - } - + uint64_t TypeStorageSize = Context.getTypeSize(FieldTy); + uint64_t TypeWidth = Context.getIntWidth(FieldTy); + bool BitfieldIsOverwide = Value.ugt(TypeWidth); + + // Over-wide bitfields are an error in C or when using the MSVC bitfield + // ABI. + bool CStdConstraintViolation = + BitfieldIsOverwide && !getLangOpts().CPlusPlus; + bool MSBitfieldViolation = + Value.ugt(TypeStorageSize) && + (IsMsStruct || Context.getTargetInfo().getCXXABI().isMicrosoft()); + if (CStdConstraintViolation || MSBitfieldViolation) { + unsigned DiagWidth = + CStdConstraintViolation ? TypeWidth : TypeStorageSize; + if (FieldName) + return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width) + << FieldName << (unsigned)Value.getZExtValue() + << !CStdConstraintViolation << DiagWidth; + + return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width) + << (unsigned)Value.getZExtValue() << !CStdConstraintViolation + << DiagWidth; + } + + // Warn on types where the user might conceivably expect to get all + // specified bits as value bits: that's all integral types other than + // 'bool'. + if (BitfieldIsOverwide && !FieldTy->isBooleanType()) { if (FieldName) - Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_size) - << FieldName << (unsigned)Value.getZExtValue() - << (unsigned)TypeSize; + Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width) + << FieldName << (unsigned)Value.getZExtValue() + << (unsigned)TypeWidth; else - Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size) - << (unsigned)Value.getZExtValue() << (unsigned)TypeSize; + Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width) + << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth; } } @@ -12866,9 +13211,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { SourceLocation Loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(Loc)) { if (!FD->hasAttr<UnavailableAttr>()) - FD->addAttr(UnavailableAttr::CreateImplicit(Context, - "this system field has retaining ownership", - Loc)); + FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", + UnavailableAttr::IR_ARCFieldWithOwnership, Loc)); return false; } } @@ -12876,7 +13220,7 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member : diag::err_illegal_union_or_anon_struct_member) - << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; + << FD->getParent()->isUnion() << FD->getDeclName() << member; DiagnoseNontrivial(RDecl, member); return !getLangOpts().CPlusPlus11; } @@ -13237,9 +13581,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, SourceLocation loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(loc)) { if (!FD->hasAttr<UnavailableAttr>()) { - FD->addAttr(UnavailableAttr::CreateImplicit(Context, - "this system field has retaining ownership", - loc)); + FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", + UnavailableAttr::IR_ARCFieldWithOwnership, loc)); } } else { Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) @@ -13687,10 +14030,12 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName, ForRedeclaration); auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl); + if (!PrevECD) + return SkipBodyInfo(); + + EnumDecl *PrevED = cast<EnumDecl>(PrevECD->getDeclContext()); NamedDecl *Hidden; - if (PrevECD && - !hasVisibleDefinition(cast<NamedDecl>(PrevECD->getDeclContext()), - &Hidden)) { + if (!PrevED->getDeclName() && !hasVisibleDefinition(PrevED, &Hidden)) { SkipBodyInfo Skip; Skip.Previous = Hidden; return Skip; @@ -13722,12 +14067,27 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, PrevDecl = nullptr; } + // C++ [class.mem]p15: + // If T is the name of a class, then each of the following shall have a name + // different from T: + // - every enumerator of every member of class T that is an unscoped + // enumerated type + if (!TheEnumDecl->isScoped()) + DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(), + DeclarationNameInfo(Id, IdLoc)); + + EnumConstantDecl *New = + CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val); + if (!New) + return nullptr; + if (PrevDecl) { // When in C++, we may get a TagDecl with the same name; in this case the // enum constant will 'hide' the tag. assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) && "Received TagDecl when not in C++!"); - if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) { + if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S) && + shouldLinkPossiblyHiddenDecl(PrevDecl, New)) { if (isa<EnumConstantDecl>(PrevDecl)) Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id; else @@ -13737,26 +14097,12 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, } } - // C++ [class.mem]p15: - // If T is the name of a class, then each of the following shall have a name - // different from T: - // - every enumerator of every member of class T that is an unscoped - // enumerated type - if (!TheEnumDecl->isScoped()) - DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(), - DeclarationNameInfo(Id, IdLoc)); - - EnumConstantDecl *New = - CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val); + // Process attributes. + if (Attr) ProcessDeclAttributeList(S, New, Attr); - if (New) { - // Process attributes. - if (Attr) ProcessDeclAttributeList(S, New, Attr); - - // Register this decl in the current scope stack. - New->setAccess(TheEnumDecl->getAccess()); - PushOnScopeChains(New, S); - } + // Register this decl in the current scope stack. + New->setAccess(TheEnumDecl->getAccess()); + PushOnScopeChains(New, S); ActOnDocumentableDecl(New); @@ -13803,6 +14149,7 @@ static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) { return false; } +namespace { struct DupKey { int64_t val; bool isTombstoneOrEmptyKey; @@ -13826,6 +14173,7 @@ struct DenseMapInfoDupKey { LHS.val == RHS.val; } }; +} // end anonymous namespace // Emits a warning when an element is implicitly set a value that // a previous element has already been set to. @@ -13937,17 +14285,22 @@ 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"); +bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, + bool AllowMask) const { + assert(ED->hasAttr<FlagEnumAttr>() && "looking for value in non-flag enum"); + assert(ED->isCompleteDefinition() && "expected enum definition"); - llvm::APInt FlagMask = ~FEAttr->getFlagBits(); - unsigned Width = FlagMask.getBitWidth(); + auto R = FlagBitsCache.insert(std::make_pair(ED, llvm::APInt())); + llvm::APInt &FlagBits = R.first->second; - // We will try a zero-extended value for the regular check first. - llvm::APInt ExtVal = Val.zextOrSelf(Width); + if (R.second) { + for (auto *E : ED->enumerators()) { + const auto &EVal = E->getInitVal(); + // Only single-bit enumerators introduce new flag values. + if (EVal.isPowerOf2()) + FlagBits = FlagBits.zextOrSelf(EVal.getBitWidth()) | EVal; + } + } // 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 @@ -13957,27 +14310,8 @@ Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, // 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; + llvm::APInt FlagMask = ~FlagBits.zextOrTrunc(Val.getBitWidth()); + return !(FlagMask & Val) || (AllowMask && !(FlagMask & ~Val)); } void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, @@ -14131,13 +14465,8 @@ 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. If we have a flag type, we also prepare the - // FlagBits cache. + // the type of the enum if needed. for (auto *D : Elements) { auto *ECD = cast_or_null<EnumConstantDecl>(D); if (!ECD) continue; // Already issued a diagnostic. @@ -14169,7 +14498,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // enum-specifier, each enumerator has the type of its // enumeration. ECD->setType(EnumType); - goto flagbits; + continue; } else { NewTy = BestType; NewWidth = BestWidth; @@ -14196,37 +14525,26 @@ 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) { + Enum->completeDefinition(BestType, BestPromotionType, + NumPositiveBits, NumNegativeBits); + + CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType); + + if (Enum->hasAttr<FlagEnumAttr>()) { 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)) + if (InitVal != 0 && !InitVal.isPowerOf2() && + !IsValueInFlagEnum(Enum, InitVal, true)) Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range) << ECD << Enum; } } - - - Enum->completeDefinition(BestType, BestPromotionType, - NumPositiveBits, NumNegativeBits); - - CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType); - // Now that the enum type is defined, ensure it's not been underaligned. if (Enum->hasAttrs()) CheckAlignasUnderalignment(Enum); @@ -14245,17 +14563,15 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, } static void checkModuleImportContext(Sema &S, Module *M, - SourceLocation ImportLoc, - DeclContext *DC) { + SourceLocation ImportLoc, DeclContext *DC, + bool FromInclude = false) { + SourceLocation ExternCLoc; + if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) { switch (LSD->getLanguage()) { case LinkageSpecDecl::lang_c: - if (!M->IsExternC) { - S.Diag(ImportLoc, diag::err_module_import_in_extern_c) - << M->getFullModuleName(); - S.Diag(LSD->getLocStart(), diag::note_module_import_in_extern_c); - return; - } + if (ExternCLoc.isInvalid()) + ExternCLoc = LSD->getLocStart(); break; case LinkageSpecDecl::lang_cxx: break; @@ -14265,15 +14581,25 @@ static void checkModuleImportContext(Sema &S, Module *M, while (isa<LinkageSpecDecl>(DC)) DC = DC->getParent(); + if (!isa<TranslationUnitDecl>(DC)) { - S.Diag(ImportLoc, diag::err_module_import_not_at_top_level) - << M->getFullModuleName() << DC; + S.Diag(ImportLoc, (FromInclude && S.isModuleVisible(M)) + ? diag::ext_module_import_not_at_top_level_noop + : diag::err_module_import_not_at_top_level_fatal) + << M->getFullModuleName() << DC; S.Diag(cast<Decl>(DC)->getLocStart(), - diag::note_module_import_not_at_top_level) - << DC; + diag::note_module_import_not_at_top_level) << DC; + } else if (!M->IsExternC && ExternCLoc.isValid()) { + S.Diag(ImportLoc, diag::ext_module_import_in_extern_c) + << M->getFullModuleName(); + S.Diag(ExternCLoc, diag::note_module_import_in_extern_c); } } +void Sema::diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc) { + return checkModuleImportContext(*this, M, ImportLoc, CurContext); +} + DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc, ModuleIdPath Path) { @@ -14318,7 +14644,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, } void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { - checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext); + checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, 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 @@ -14394,12 +14720,14 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, // 1) declares a function or a variable // 2) has external linkage // already exists, add a label attribute to it. - if (PrevDecl && - (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)) && - PrevDecl->hasExternalFormalLinkage()) - PrevDecl->addAttr(Attr); + if (PrevDecl && (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl))) { + if (isDeclExternC(PrevDecl)) + PrevDecl->addAttr(Attr); + else + Diag(PrevDecl->getLocation(), diag::warn_redefine_extname_not_applied) + << /*Variable*/(isa<FunctionDecl>(PrevDecl) ? 0 : 1) << PrevDecl; // Otherwise, add a label atttibute to ExtnameUndeclaredIdentifiers. - else + } else (void)ExtnameUndeclaredIdentifiers.insert(std::make_pair(Name, Attr)); } @@ -14426,7 +14754,7 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, LookupOrdinaryName); WeakInfo W = WeakInfo(Name, NameLoc); - if (PrevDecl) { + if (PrevDecl && (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl))) { if (!PrevDecl->hasAttr<AliasAttr>()) if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl)) DeclApplyPragmaWeak(TUScope, ND, W); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index 191dbd0..5a0f0f8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -244,11 +244,12 @@ static bool checkUInt32Argument(Sema &S, const AttributeList &Attr, /// \brief Diagnose mutually exclusive attributes when present on a given /// declaration. Returns true if diagnosed. template <typename AttrTy> -static bool checkAttrMutualExclusion(Sema &S, Decl *D, - const AttributeList &Attr) { +static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range, + IdentifierInfo *Ident) { if (AttrTy *A = D->getAttr<AttrTy>()) { - S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) - << Attr.getName() << A; + S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) << Ident + << A; + S.Diag(A->getLocation(), diag::note_conflicting_attribute); return true; } return false; @@ -315,7 +316,7 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr, Diag(Loc->Loc, diag::err_attribute_argument_type) << Attr.getName() << AANT_ArgumentString << FixItHint::CreateInsertion(Loc->Loc, "\"") - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\""); + << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\""); Str = Loc->Ident->getName(); if (ArgLocation) *ArgLocation = Loc->Loc; @@ -432,11 +433,10 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { // Else check if any base classes have a capability. if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { CXXBasePaths BPaths(false, false); - if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &P, - void *) { - return BS->getType()->getAs<RecordType>() - ->getDecl()->hasAttr<CapabilityAttr>(); - }, nullptr, BPaths)) + if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) { + const auto *Type = BS->getType()->getAs<RecordType>(); + return Type->getDecl()->hasAttr<CapabilityAttr>(); + }, BPaths)) return true; } return false; @@ -629,13 +629,10 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, // Check that this attribute only applies to lockable types. QualType QT = cast<ValueDecl>(D)->getType(); - if (!QT->isDependentType()) { - const RecordType *RT = getRecordType(QT); - if (!RT || !RT->getDecl()->hasAttr<CapabilityAttr>()) { - S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable) - << Attr.getName(); - return false; - } + if (!QT->isDependentType() && !typeHasCapability(S, QT)) { + S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable) + << Attr.getName(); + return false; } // Check that all arguments are lockable objects. @@ -812,6 +809,43 @@ static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } +static void handlePassObjectSizeAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (D->hasAttr<PassObjectSizeAttr>()) { + S.Diag(D->getLocStart(), diag::err_attribute_only_once_per_parameter) + << Attr.getName(); + return; + } + + Expr *E = Attr.getArgAsExpr(0); + uint32_t Type; + if (!checkUInt32Argument(S, Attr, E, Type, /*Idx=*/1)) + return; + + // pass_object_size's argument is passed in as the second argument of + // __builtin_object_size. So, it has the same constraints as that second + // argument; namely, it must be in the range [0, 3]. + if (Type > 3) { + S.Diag(E->getLocStart(), diag::err_attribute_argument_outof_range) + << Attr.getName() << 0 << 3 << E->getSourceRange(); + return; + } + + // pass_object_size is only supported on constant pointer parameters; as a + // kindness to users, we allow the parameter to be non-const for declarations. + // At this point, we have no clue if `D` belongs to a function declaration or + // definition, so we defer the constness check until later. + if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) { + S.Diag(D->getLocStart(), diag::err_attribute_pointers_only) + << Attr.getName() << 1; + return; + } + + D->addAttr(::new (S.Context) + PassObjectSizeAttr(Attr.getRange(), S.Context, (int)Type, + Attr.getAttributeSpellingListIndex())); +} + static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) { ConsumableAttr::ConsumedState DefaultState; @@ -1039,17 +1073,14 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { - // If the alignment is less than or equal to 8 bits, the packed attribute - // has no effect. + // Report warning about changed offset in the newer compiler versions. if (!FD->getType()->isDependentType() && - !FD->getType()->isIncompleteType() && + !FD->getType()->isIncompleteType() && FD->isBitField() && S.Context.getTypeAlign(FD->getType()) <= 8) - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) - << Attr.getName() << FD->getType(); - else - FD->addAttr(::new (S.Context) - PackedAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield); + + FD->addAttr(::new (S.Context) PackedAttr( + Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -1165,10 +1196,12 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr, SourceRange TypeRange, bool isReturnValue = false) { if (!S.isValidPointerAttrType(T)) { - S.Diag(Attr.getLoc(), isReturnValue - ? diag::warn_attribute_return_pointers_only - : diag::warn_attribute_pointers_only) - << Attr.getName() << AttrParmRange << TypeRange; + if (isReturnValue) + S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only) + << Attr.getName() << AttrParmRange << TypeRange; + else + S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only) + << Attr.getName() << AttrParmRange << TypeRange << 0; return false; } return true; @@ -1312,6 +1345,17 @@ void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, AssumeAlignedAttr(AttrRange, Context, E, OE, SpellingListIndex)); } +/// Normalize the attribute, __foo__ becomes foo. +/// Returns true if normalization was applied. +static bool normalizeName(StringRef &AttrName) { + if (AttrName.size() > 4 && AttrName.startswith("__") && + AttrName.endswith("__")) { + AttrName = AttrName.drop_front(2).drop_back(2); + return true; + } + return false; +} + static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { // This attribute must be applied to a function declaration. The first // argument to the attribute must be an identifier, the name of the resource, @@ -1353,11 +1397,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident; - // Normalize the argument, __foo__ becomes foo. StringRef ModuleName = Module->getName(); - if (ModuleName.startswith("__") && ModuleName.endswith("__") && - ModuleName.size() > 4) { - ModuleName = ModuleName.drop_front(2).drop_back(2); + if (normalizeName(ModuleName)) { Module = &S.PP.getIdentifierTable().get(ModuleName); } @@ -1519,7 +1560,7 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<HotAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<HotAttr>(S, D, Attr.getRange(), Attr.getName())) return; D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context, @@ -1527,7 +1568,7 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr.getRange(), Attr.getName())) return; D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context, @@ -1569,12 +1610,22 @@ static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CPlusPlus) { S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang) - << Attr.getName() << AttributeLangSupport::Cpp; + << Attr.getName() << AttributeLangSupport::Cpp; return; } - D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + if (CommonAttr *CA = S.mergeCommonAttr(D, Attr.getRange(), Attr.getName(), + Attr.getAttributeSpellingListIndex())) + D->addAttr(CA); +} + +static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, Attr.getRange(), + Attr.getName())) + return; + + D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { @@ -1613,7 +1664,7 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, !VD->getType()->isFunctionPointerType())) { S.Diag(Attr.getLoc(), Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type - : diag::warn_attribute_wrong_decl_type) + : diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } @@ -1697,6 +1748,26 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, Attr.getAttributeSpellingListIndex())); } +static void handleNotTailCalledAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr.getRange(), + Attr.getName())) + return; + + D->addAttr(::new (S.Context) NotTailCalledAttr( + Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); +} + +static void handleDisableTailCallsAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (checkAttrMutualExclusion<NakedAttr>(S, D, Attr.getRange(), + Attr.getName())) + return; + + D->addAttr(::new (S.Context) DisableTailCallsAttr( + Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); +} + static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasLocalStorage()) { @@ -1825,12 +1896,24 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, - bool Override, + AvailabilityMergeKind AMK, unsigned AttrSpellingListIndex) { VersionTuple MergedIntroduced = Introduced; VersionTuple MergedDeprecated = Deprecated; VersionTuple MergedObsoleted = Obsoleted; bool FoundAny = false; + bool OverrideOrImpl = false; + switch (AMK) { + case AMK_None: + case AMK_Redeclaration: + OverrideOrImpl = false; + break; + + case AMK_Override: + case AMK_ProtocolImplementation: + OverrideOrImpl = true; + break; + } if (D->hasAttrs()) { AttrVec &Attrs = D->getAttrs(); @@ -1847,30 +1930,46 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, continue; } + // If there is an existing availability attribute for this platform that + // is explicit and the new one is implicit use the explicit one and + // discard the new implicit attribute. + if (OldAA->getRange().isValid() && Range.isInvalid()) { + return nullptr; + } + + // If there is an existing attribute for this platform that is implicit + // and the new attribute is explicit then erase the old one and + // continue processing the attributes. + if (Range.isValid() && OldAA->getRange().isInvalid()) { + Attrs.erase(Attrs.begin() + i); + --e; + continue; + } + FoundAny = true; VersionTuple OldIntroduced = OldAA->getIntroduced(); VersionTuple OldDeprecated = OldAA->getDeprecated(); VersionTuple OldObsoleted = OldAA->getObsoleted(); bool OldIsUnavailable = OldAA->getUnavailable(); - if (!versionsMatch(OldIntroduced, Introduced, Override) || - !versionsMatch(Deprecated, OldDeprecated, Override) || - !versionsMatch(Obsoleted, OldObsoleted, Override) || + if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) || + !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) || + !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) || !(OldIsUnavailable == IsUnavailable || - (Override && !OldIsUnavailable && IsUnavailable))) { - if (Override) { + (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) { + if (OverrideOrImpl) { int Which = -1; VersionTuple FirstVersion; VersionTuple SecondVersion; - if (!versionsMatch(OldIntroduced, Introduced, Override)) { + if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) { Which = 0; FirstVersion = OldIntroduced; SecondVersion = Introduced; - } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) { + } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) { Which = 1; FirstVersion = Deprecated; SecondVersion = OldDeprecated; - } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) { + } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) { Which = 2; FirstVersion = Obsoleted; SecondVersion = OldObsoleted; @@ -1879,15 +1978,20 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, if (Which == -1) { Diag(OldAA->getLocation(), diag::warn_mismatched_availability_override_unavail) - << AvailabilityAttr::getPrettyPlatformName(Platform->getName()); + << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) + << (AMK == AMK_Override); } else { Diag(OldAA->getLocation(), diag::warn_mismatched_availability_override) << Which << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) - << FirstVersion.getAsString() << SecondVersion.getAsString(); + << FirstVersion.getAsString() << SecondVersion.getAsString() + << (AMK == AMK_Override); } - Diag(Range.getBegin(), diag::note_overridden_method); + if (AMK == AMK_Override) + Diag(Range.getBegin(), diag::note_overridden_method); + else + Diag(Range.getBegin(), diag::note_protocol_method); } else { Diag(OldAA->getLocation(), diag::warn_mismatched_availability); Diag(Range.getBegin(), diag::note_previous_attribute); @@ -1930,11 +2034,11 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, MergedObsoleted == Obsoleted) return nullptr; - // Only create a new attribute if !Override, but we want to do + // Only create a new attribute if !OverrideOrImpl, but we want to do // the checking. if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced, MergedDeprecated, MergedObsoleted) && - !Override) { + !OverrideOrImpl) { return ::new (Context) AvailabilityAttr(Range, Context, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable, Message, @@ -1975,10 +2079,78 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, - /*Override=*/false, + Sema::AMK_None, Index); if (NewAttr) D->addAttr(NewAttr); + + // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning + // matches before the start of the watchOS platform. + if (S.Context.getTargetInfo().getTriple().isWatchOS()) { + IdentifierInfo *NewII = nullptr; + if (II->getName() == "ios") + NewII = &S.Context.Idents.get("watchos"); + else if (II->getName() == "ios_app_extension") + NewII = &S.Context.Idents.get("watchos_app_extension"); + + if (NewII) { + auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple { + if (Version.empty()) + return Version; + auto Major = Version.getMajor(); + auto NewMajor = Major >= 9 ? Major - 7 : 0; + if (NewMajor >= 2) { + if (Version.getMinor().hasValue()) { + if (Version.getSubminor().hasValue()) + return VersionTuple(NewMajor, Version.getMinor().getValue(), + Version.getSubminor().getValue()); + else + return VersionTuple(NewMajor, Version.getMinor().getValue()); + } + } + + return VersionTuple(2, 0); + }; + + auto NewIntroduced = adjustWatchOSVersion(Introduced.Version); + auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version); + auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version); + + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, + SourceRange(), + NewII, + NewIntroduced, + NewDeprecated, + NewObsoleted, + IsUnavailable, Str, + Sema::AMK_None, + Index); + if (NewAttr) + D->addAttr(NewAttr); + } + } else if (S.Context.getTargetInfo().getTriple().isTvOS()) { + // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning + // matches before the start of the tvOS platform. + IdentifierInfo *NewII = nullptr; + if (II->getName() == "ios") + NewII = &S.Context.Idents.get("tvos"); + else if (II->getName() == "ios_app_extension") + NewII = &S.Context.Idents.get("tvos_app_extension"); + + if (NewII) { + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, + SourceRange(), + NewII, + Introduced.Version, + Deprecated.Version, + Obsoleted.Version, + IsUnavailable, Str, + Sema::AMK_None, + Index); + if (NewAttr) + D->addAttr(NewAttr); + } + } } template <class T> @@ -2492,17 +2664,17 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, IdxExpr, Idx)) return; - // make sure the format string is really a string + // Make sure the format string is really a string. QualType Ty = getFunctionOrMethodParamType(D, Idx); - bool not_nsstring_type = !isNSStringType(Ty, S.Context); - if (not_nsstring_type && + bool NotNSStringTy = !isNSStringType(Ty, S.Context); + if (NotNSStringTy && !isCFStringType(Ty, S.Context) && (!Ty->isPointerType() || !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { S.Diag(Attr.getLoc(), diag::err_format_attribute_not) - << (not_nsstring_type ? "a string type" : "an NSString") - << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0); + << "a string type" << IdxExpr->getSourceRange() + << getFunctionOrMethodParamRange(D, 0); return; } Ty = getFunctionOrMethodResultType(D); @@ -2511,7 +2683,7 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { (!Ty->isPointerType() || !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not) - << (not_nsstring_type ? "string type" : "NSString") + << (NotNSStringTy ? "string type" : "NSString") << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0); return; } @@ -2588,7 +2760,7 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, if (prioritynum < 101 || prioritynum > 65535) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range) - << E->getSourceRange(); + << E->getSourceRange() << Attr.getName() << 101 << 65535; Attr.setInvalid(); return; } @@ -2635,9 +2807,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; StringRef Format = II->getName(); - // Normalize the argument, __foo__ becomes foo. - if (Format.startswith("__") && Format.endswith("__")) { - Format = Format.substr(2, Format.size() - 4); + if (normalizeName(Format)) { // If we've modified the string name, we need a new identifier for it. II = &S.Context.Idents.get(Format); } @@ -2858,7 +3028,7 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E, } if (!E->isValueDependent()) { - llvm::APSInt Alignment(32); + llvm::APSInt Alignment; ExprResult ICE = VerifyIntegerConstantExpression(E, &Alignment, diag::err_align_value_attribute_argument_not_int, @@ -2972,7 +3142,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, } // FIXME: Cache the number on the Attr object? - llvm::APSInt Alignment(32); + llvm::APSInt Alignment; ExprResult ICE = VerifyIntegerConstantExpression(E, &Alignment, diag::err_aligned_attribute_argument_not_int, @@ -2980,42 +3150,44 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, if (ICE.isInvalid()) return; + uint64_t AlignVal = Alignment.getZExtValue(); + // C++11 [dcl.align]p2: // -- if the constant expression evaluates to zero, the alignment // specifier shall have no effect // C11 6.7.5p6: // An alignment specification of zero has no effect. if (!(TmpAttr.isAlignas() && !Alignment)) { - if(!llvm::isPowerOf2_64(Alignment.getZExtValue())) { + if (!llvm::isPowerOf2_64(AlignVal)) { Diag(AttrLoc, diag::err_alignment_not_power_of_two) << E->getSourceRange(); return; } - if (Context.getTargetInfo().isTLSSupported()) { - if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) { - if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (VD->getTLSKind()) { - CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign); - if (Alignment.getSExtValue() > MaxAlignChars.getQuantity()) { - Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum) - << (unsigned)Alignment.getZExtValue() << VD - << (unsigned)MaxAlignChars.getQuantity(); - return; - } - } - } - } - } } // Alignment calculations can wrap around if it's greater than 2**28. - unsigned MaxValidAlignment = TmpAttr.isDeclspec() ? 8192 : 268435456; - if (Alignment.getZExtValue() > MaxValidAlignment) { + unsigned MaxValidAlignment = + Context.getTargetInfo().getTriple().isOSBinFormatCOFF() ? 8192 + : 268435456; + if (AlignVal > MaxValidAlignment) { Diag(AttrLoc, diag::err_attribute_aligned_too_great) << MaxValidAlignment << E->getSourceRange(); return; } + if (Context.getTargetInfo().isTLSSupported()) { + unsigned MaxTLSAlign = + Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign()) + .getQuantity(); + auto *VD = dyn_cast<VarDecl>(D); + if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD && + VD->getTLSKind() != VarDecl::TLS_None) { + Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum) + << (unsigned)AlignVal << VD << MaxTLSAlign; + return; + } + } + AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true, ICE.get(), SpellingListIndex); AA->setPackExpansion(IsPackExpansion); @@ -3098,40 +3270,31 @@ bool Sema::checkMSInheritanceAttrOnDefinition( return true; } -/// handleModeAttr - This attribute modifies the width of a decl with primitive -/// type. -/// -/// Despite what would be logical, the mode attribute is a decl attribute, not a -/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be -/// HImode, not an intermediate pointer. -static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // This attribute isn't documented, but glibc uses it. It changes - // the width of an int or unsigned int to the specified size. - if (!Attr.isArgIdent(0)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() - << AANT_ArgumentIdentifier; - return; - } - - IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; - StringRef Str = Name->getName(); - - // Normalize the attribute name, __foo__ becomes foo. - if (Str.startswith("__") && Str.endswith("__")) - Str = Str.substr(2, Str.size() - 4); - - unsigned DestWidth = 0; - bool IntegerMode = true; - bool ComplexMode = false; +/// parseModeAttrArg - Parses attribute mode string and returns parsed type +/// attribute. +static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, + bool &IntegerMode, bool &ComplexMode) { switch (Str.size()) { case 2: switch (Str[0]) { - case 'Q': DestWidth = 8; break; - case 'H': DestWidth = 16; break; - case 'S': DestWidth = 32; break; - case 'D': DestWidth = 64; break; - case 'X': DestWidth = 96; break; - case 'T': DestWidth = 128; break; + case 'Q': + DestWidth = 8; + break; + case 'H': + DestWidth = 16; + break; + case 'S': + DestWidth = 32; + break; + case 'D': + DestWidth = 64; + break; + case 'X': + DestWidth = 96; + break; + case 'T': + DestWidth = 128; + break; } if (Str[1] == 'F') { IntegerMode = false; @@ -3159,6 +3322,52 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); break; } +} + +/// handleModeAttr - This attribute modifies the width of a decl with primitive +/// type. +/// +/// Despite what would be logical, the mode attribute is a decl attribute, not a +/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be +/// HImode, not an intermediate pointer. +static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // This attribute isn't documented, but glibc uses it. It changes + // the width of an int or unsigned int to the specified size. + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() + << AANT_ArgumentIdentifier; + return; + } + + IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; + StringRef Str = Name->getName(); + + normalizeName(Str); + + unsigned DestWidth = 0; + bool IntegerMode = true; + bool ComplexMode = false; + llvm::APInt VectorSize(64, 0); + if (Str.size() >= 4 && Str[0] == 'V') { + // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2). + size_t StrSize = Str.size(); + size_t VectorStringLength = 0; + while ((VectorStringLength + 1) < StrSize && + isdigit(Str[VectorStringLength + 1])) + ++VectorStringLength; + if (VectorStringLength && + !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && + VectorSize.isPowerOf2()) { + parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth, + IntegerMode, ComplexMode); + S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated); + } else { + VectorSize = 0; + } + } + + if (!VectorSize) + parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode); QualType OldTy; if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) @@ -3217,7 +3426,10 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { } QualType NewTy = NewElemTy; - if (const VectorType *OldVT = OldTy->getAs<VectorType>()) { + if (VectorSize.getBoolValue()) { + NewTy = S.Context.getVectorType(NewTy, VectorSize.getZExtValue(), + VectorType::GenericVector); + } else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) { // Complex machine mode does not support base vector types. if (ComplexMode) { S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type); @@ -3280,6 +3492,42 @@ AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range, AttrSpellingListIndex); } +CommonAttr *Sema::mergeCommonAttr(Decl *D, SourceRange Range, + IdentifierInfo *Ident, + unsigned AttrSpellingListIndex) { + if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, Range, Ident)) + return nullptr; + + return ::new (Context) CommonAttr(Range, Context, AttrSpellingListIndex); +} + +InternalLinkageAttr * +Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range, + IdentifierInfo *Ident, + unsigned AttrSpellingListIndex) { + if (auto VD = dyn_cast<VarDecl>(D)) { + // Attribute applies to Var but not any subclass of it (like ParmVar, + // ImplicitParm or VarTemplateSpecialization). + if (VD->getKind() != Decl::Var) { + Diag(Range.getBegin(), diag::warn_attribute_wrong_decl_type) + << Ident << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass + : ExpectedVariableOrFunction); + return nullptr; + } + // Attribute does not apply to non-static local variables. + if (VD->hasLocalStorage()) { + Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); + return nullptr; + } + } + + if (checkAttrMutualExclusion<CommonAttr>(*this, D, Range, Ident)) + return nullptr; + + return ::new (Context) + InternalLinkageAttr(Range, Context, AttrSpellingListIndex); +} + MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex) { if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) { @@ -3316,6 +3564,10 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range, static void handleAlwaysInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, Attr.getRange(), + Attr.getName())) + return; + if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr( D, Attr.getRange(), Attr.getName(), Attr.getAttributeSpellingListIndex())) @@ -3349,6 +3601,7 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { D->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); + } static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3645,7 +3898,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx); if (!BufferTy->isPointerType()) { S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) - << Attr.getName(); + << Attr.getName() << 0; } } @@ -3898,7 +4151,8 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, static void handleCFAuditedTransferAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr.getRange(), + Attr.getName())) return; D->addAttr(::new (S.Context) @@ -3908,7 +4162,8 @@ static void handleCFAuditedTransferAttr(Sema &S, Decl *D, static void handleCFUnknownTransferAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr)) + if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr.getRange(), + Attr.getName())) return; D->addAttr(::new (S.Context) @@ -4231,14 +4486,86 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, D->addAttr(UsedAttr::CreateImplicit(S.Context)); } +static void handleMipsInterruptAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // Only one optional argument permitted. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) + << Attr.getName() << 1; + return; + } + + StringRef Str; + SourceLocation ArgLoc; + + if (Attr.getNumArgs() == 0) + Str = ""; + else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc)) + return; + + // Semantic checks for a function with the 'interrupt' attribute for MIPS: + // a) Must be a function. + // b) Must have no parameters. + // c) Must have the 'void' return type. + // d) Cannot have the 'mips16' attribute, as that instruction set + // lacks the 'eret' instruction. + // e) The attribute itself must either have no argument or one of the + // valid interrupt types, see [MipsInterruptDocs]. + + if (!isFunctionOrMethod(D)) { + S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) + << "'interrupt'" << ExpectedFunctionOrMethod; + return; + } + + if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) { + S.Diag(D->getLocation(), diag::warn_mips_interrupt_attribute) + << 0; + return; + } + + if (!getFunctionOrMethodResultType(D)->isVoidType()) { + S.Diag(D->getLocation(), diag::warn_mips_interrupt_attribute) + << 1; + return; + } + + if (checkAttrMutualExclusion<Mips16Attr>(S, D, Attr.getRange(), + Attr.getName())) + return; + + MipsInterruptAttr::InterruptType Kind; + if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << Attr.getName() << "'" + std::string(Str) + "'"; + return; + } + + D->addAttr(::new (S.Context) MipsInterruptAttr( + Attr.getLoc(), S.Context, Kind, Attr.getAttributeSpellingListIndex())); +} + static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Dispatch the interrupt attribute based on the current target. if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430) handleMSP430InterruptAttr(S, D, Attr); + else if (S.Context.getTargetInfo().getTriple().getArch() == + llvm::Triple::mipsel || + S.Context.getTargetInfo().getTriple().getArch() == + llvm::Triple::mips) + handleMipsInterruptAttr(S, D, Attr); else handleARMInterruptAttr(S, D, Attr); } +static void handleMips16Attribute(Sema &S, Decl *D, const AttributeList &Attr) { + if (checkAttrMutualExclusion<MipsInterruptAttr>(S, D, Attr.getRange(), + Attr.getName())) + return; + + handleSimpleAttribute<Mips16Attr>(S, D, Attr); +} + static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const AttributeList &Attr) { uint32_t NumRegs; @@ -4334,6 +4661,14 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) { } } + if (auto *MD = dyn_cast<CXXMethodDecl>(D)) { + if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && + MD->getParent()->isLambda()) { + S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A.getName(); + return; + } + } + unsigned Index = A.getAttributeSpellingListIndex(); Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport ? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index) @@ -4509,8 +4844,10 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, const AttributeList &Attr) { + StringRef AttrName = Attr.getName()->getName(); + normalizeName(AttrName); std::string SanitizerName = - llvm::StringSwitch<std::string>(Attr.getName()->getName()) + llvm::StringSwitch<std::string>(AttrName) .Case("no_address_safety_analysis", "address") .Case("no_sanitize_address", "address") .Case("no_sanitize_thread", "thread") @@ -4520,6 +4857,14 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +static void handleInternalLinkageAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (InternalLinkageAttr *Internal = + S.mergeInternalLinkageAttr(D, Attr.getRange(), Attr.getName(), + Attr.getAttributeSpellingListIndex())) + D->addAttr(Internal); +} + /// 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. @@ -4583,7 +4928,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, // which do not apply to the current target architecture are treated as // though they were unknown attributes. if (Attr.getKind() == AttributeList::UnknownAttribute || - !Attr.existsInTarget(S.Context.getTargetInfo().getTriple())) { + !Attr.existsInTarget(S.Context.getTargetInfo())) { S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ? diag::warn_unhandled_ms_attribute_ignored : diag::warn_unknown_attribute_ignored) @@ -4610,7 +4955,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleDLLAttr(S, D, Attr); break; case AttributeList::AT_Mips16: - handleSimpleAttribute<Mips16Attr>(S, D, Attr); + handleMips16Attribute(S, D, Attr); break; case AttributeList::AT_NoMips16: handleSimpleAttribute<NoMips16Attr>(S, D, Attr); @@ -4663,6 +5008,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_CUDAConstant: handleSimpleAttribute<CUDAConstantAttr>(S, D, Attr); break; + case AttributeList::AT_PassObjectSize: + handlePassObjectSizeAttr(S, D, Attr); + break; case AttributeList::AT_Constructor: handleConstructorAttr(S, D, Attr); break; @@ -4723,6 +5071,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Mode: handleModeAttr(S, D, Attr); break; + case AttributeList::AT_NoAlias: + handleSimpleAttribute<NoAliasAttr>(S, D, Attr); + break; case AttributeList::AT_NoCommon: handleSimpleAttribute<NoCommonAttr>(S, D, Attr); break; @@ -4754,7 +5105,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleHotAttr(S, D, Attr); break; case AttributeList::AT_Naked: - handleSimpleAttribute<NakedAttr>(S, D, Attr); + handleNakedAttr(S, D, Attr); break; case AttributeList::AT_NoReturn: handleNoReturnAttr(S, D, Attr); @@ -4874,6 +5225,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ReturnsTwice: handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr); break; + case AttributeList::AT_NotTailCalled: + handleNotTailCalledAttr(S, D, Attr); + break; + case AttributeList::AT_DisableTailCalls: + handleDisableTailCallsAttr(S, D, Attr); + break; case AttributeList::AT_Used: handleUsedAttr(S, D, Attr); break; @@ -4958,6 +5315,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_OpenCLImageAccess: handleSimpleAttribute<OpenCLImageAccessAttr>(S, D, Attr); break; + case AttributeList::AT_InternalLinkage: + handleInternalLinkageAttr(S, D, Attr); + break; // Microsoft attributes: case AttributeList::AT_MSNoVTable: @@ -5299,26 +5659,50 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { } /// Is the given declaration allowed to use a forbidden type? -static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) { +/// If so, it'll still be annotated with an attribute that makes it +/// illegal to actually use. +static bool isForbiddenTypeAllowed(Sema &S, Decl *decl, + const DelayedDiagnostic &diag, + UnavailableAttr::ImplicitReason &reason) { // Private ivars are always okay. Unfortunately, people don't // always properly make their ivars private, even in system headers. // Plus we need to make fields okay, too. - // Function declarations in sys headers will be marked unavailable. if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) && !isa<FunctionDecl>(decl)) return false; - // Require it to be declared in a system header. - return S.Context.getSourceManager().isInSystemHeader(decl->getLocation()); + // Silently accept unsupported uses of __weak in both user and system + // declarations when it's been disabled, for ease of integration with + // -fno-objc-arc files. We do have to take some care against attempts + // to define such things; for now, we've only done that for ivars + // and properties. + if ((isa<ObjCIvarDecl>(decl) || isa<ObjCPropertyDecl>(decl))) { + if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled || + diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) { + reason = UnavailableAttr::IR_ForbiddenWeak; + return true; + } + } + + // Allow all sorts of things in system headers. + if (S.Context.getSourceManager().isInSystemHeader(decl->getLocation())) { + // Currently, all the failures dealt with this way are due to ARC + // restrictions. + reason = UnavailableAttr::IR_ARCForbiddenType; + return true; + } + + return false; } /// Handle a delayed forbidden-type diagnostic. static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, Decl *decl) { - if (decl && isForbiddenTypeAllowed(S, decl)) { - decl->addAttr(UnavailableAttr::CreateImplicit(S.Context, - "this system declaration uses an unsupported type", - diag.Loc)); + auto reason = UnavailableAttr::IR_None; + if (decl && isForbiddenTypeAllowed(S, decl, diag, reason)) { + assert(reason && "didn't set reason?"); + decl->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", reason, + diag.Loc)); return; } if (S.getLangOpts().ObjCAutoRefCount) @@ -5371,6 +5755,7 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K, bool ObjCPropertyAccess) { // Diagnostics for deprecated or unavailable. unsigned diag, diag_message, diag_fwdclass_message; + unsigned diag_available_here = diag::note_availability_specified_here; // Matches 'diag::note_property_attribute' options. unsigned property_note_select; @@ -5400,6 +5785,50 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K, diag_fwdclass_message = diag::warn_unavailable_fwdclass_message; property_note_select = /* unavailable */ 1; available_here_select_kind = /* unavailable */ 0; + + if (auto attr = D->getAttr<UnavailableAttr>()) { + if (attr->isImplicit() && attr->getImplicitReason()) { + // Most of these failures are due to extra restrictions in ARC; + // reflect that in the primary diagnostic when applicable. + auto flagARCError = [&] { + if (S.getLangOpts().ObjCAutoRefCount && + S.getSourceManager().isInSystemHeader(D->getLocation())) + diag = diag::err_unavailable_in_arc; + }; + + switch (attr->getImplicitReason()) { + case UnavailableAttr::IR_None: break; + + case UnavailableAttr::IR_ARCForbiddenType: + flagARCError(); + diag_available_here = diag::note_arc_forbidden_type; + break; + + case UnavailableAttr::IR_ForbiddenWeak: + if (S.getLangOpts().ObjCWeakRuntime) + diag_available_here = diag::note_arc_weak_disabled; + else + diag_available_here = diag::note_arc_weak_no_runtime; + break; + + case UnavailableAttr::IR_ARCForbiddenConversion: + flagARCError(); + diag_available_here = diag::note_performs_forbidden_arc_conversion; + break; + + case UnavailableAttr::IR_ARCInitReturnsUnrelated: + flagARCError(); + diag_available_here = diag::note_arc_init_returns_unrelated; + break; + + case UnavailableAttr::IR_ARCFieldWithOwnership: + flagARCError(); + diag_available_here = diag::note_arc_field_with_ownership; + break; + } + } + } + break; case Sema::AD_Partial: @@ -5426,7 +5855,7 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K, S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); } - S.Diag(D->getLocation(), diag::note_availability_specified_here) + S.Diag(D->getLocation(), diag_available_here) << D << available_here_select_kind; if (K == Sema::AD_Partial) S.Diag(Loc, diag::note_partial_availability_silence) << D; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index 0d7cbf4..3f6c6b0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -162,34 +162,31 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + // If we have a throw-all spec at this point, ignore the function. + if (ComputedEST == EST_None) + return; + + switch(EST) { // If this function can throw any exceptions, make a note of that. - if (EST == EST_MSAny || EST == EST_None) { + case EST_MSAny: + case EST_None: ClearExceptions(); ComputedEST = EST; return; - } - // FIXME: If the call to this decl is using any of its default arguments, we // need to search them for potentially-throwing calls. - // If this function has a basic noexcept, it doesn't affect the outcome. - if (EST == EST_BasicNoexcept) - return; - - // If we have a throw-all spec at this point, ignore the function. - if (ComputedEST == EST_None) + case EST_BasicNoexcept: return; - // If we're still at noexcept(true) and there's a nothrow() callee, // change to that specification. - if (EST == EST_DynamicNone) { + case EST_DynamicNone: if (ComputedEST == EST_BasicNoexcept) ComputedEST = EST_DynamicNone; return; - } - // Check out noexcept specs. - if (EST == EST_ComputedNoexcept) { + case EST_ComputedNoexcept: + { FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(Self->Context); assert(NR != FunctionProtoType::NR_NoNoexcept && @@ -197,7 +194,6 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, assert(NR != FunctionProtoType::NR_Dependent && "Should not generate implicit declarations for dependent cases, " "and don't know how to handle them anyway."); - // noexcept(false) -> no spec on the new function if (NR == FunctionProtoType::NR_Throw) { ClearExceptions(); @@ -206,7 +202,9 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, // noexcept(true) won't change anything either. return; } - + default: + break; + } assert(EST == EST_Dynamic && "EST case not considered earlier."); assert(ComputedEST != EST_None && "Shouldn't collect exceptions when throw-all is guaranteed."); @@ -1232,9 +1230,9 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { Diag(Dcl->getLocation(), OK ? diag::warn_cxx11_compat_constexpr_body_no_return : diag::err_constexpr_body_no_return); - return OK; - } - if (ReturnStmts.size() > 1) { + if (!OK) + return false; + } else if (ReturnStmts.size() > 1) { Diag(ReturnStmts.back(), getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_constexpr_body_multiple_return @@ -1555,9 +1553,9 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, /// \brief Performs the actual work of attaching the given base class /// specifiers to a C++ class. -bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, - unsigned NumBases) { - if (NumBases == 0) +bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, + MutableArrayRef<CXXBaseSpecifier *> Bases) { + if (Bases.empty()) return false; // Used to keep track of which base types we have already seen, so @@ -1573,7 +1571,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // Copy non-redundant base specifiers into permanent storage. unsigned NumGoodBases = 0; bool Invalid = false; - for (unsigned idx = 0; idx < NumBases; ++idx) { + for (unsigned idx = 0; idx < Bases.size(); ++idx) { QualType NewBaseType = Context.getCanonicalType(Bases[idx]->getType()); NewBaseType = NewBaseType.getLocalUnqualifiedType(); @@ -1599,7 +1597,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, Bases[NumGoodBases++] = Bases[idx]; // Note this base's direct & indirect bases, if there could be ambiguity. - if (NumBases > 1) + if (Bases.size() > 1) NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType); if (const RecordType *Record = NewBaseType->getAs<RecordType>()) { @@ -1621,7 +1619,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, } // Attach the remaining base class specifiers to the derived class. - Class->setBases(Bases, NumGoodBases); + Class->setBases(Bases.data(), NumGoodBases); for (unsigned idx = 0; idx < NumGoodBases; ++idx) { // Check whether this direct base is inaccessible due to ambiguity. @@ -1656,21 +1654,21 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, /// ActOnBaseSpecifiers - Attach the given base specifiers to the /// class, after checking whether there are any duplicate base /// classes. -void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases, - unsigned NumBases) { - if (!ClassDecl || !Bases || !NumBases) +void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, + MutableArrayRef<CXXBaseSpecifier *> Bases) { + if (!ClassDecl || Bases.empty()) return; AdjustDeclIfTemplate(ClassDecl); - AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases, NumBases); + AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases); } /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. -bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { +bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { if (!getLangOpts().CPlusPlus) return false; - + CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); if (!DerivedRD) return false; @@ -1684,13 +1682,18 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl()) return false; - // FIXME: instantiate DerivedRD if necessary. We need a PoI for this. - return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); + // FIXME: In a modules build, do we need the entire path to be visible for us + // to be able to use the inheritance relationship? + if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) + return false; + + return DerivedRD->isDerivedFrom(BaseRD); } /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. -bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { +bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, + CXXBasePaths &Paths) { if (!getLangOpts().CPlusPlus) return false; @@ -1702,6 +1705,9 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { if (!BaseRD) return false; + if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) + return false; + return DerivedRD->isDerivedFrom(BaseRD, Paths); } @@ -1749,7 +1755,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, // explore multiple paths to determine if there is an ambiguity. CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); - bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths); + bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths); assert(DerivationOkay && "Can only be used with a derived-to-base conversion"); (void)DerivationOkay; @@ -1783,7 +1789,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, // performance isn't as much of an issue. Paths.clear(); Paths.setRecordingPaths(true); - bool StillOkay = IsDerivedFrom(Derived, Base, Paths); + bool StillOkay = IsDerivedFrom(Loc, Derived, Base, Paths); assert(StillOkay && "Can only be used with a derived-to-base conversion"); (void)StillOkay; @@ -2759,7 +2765,8 @@ static bool FindBaseInitializer(Sema &SemaRef, // virtual base class. CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); - if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl), + if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(), + SemaRef.Context.getTypeDeclType(ClassDecl), BaseType, Paths)) { for (CXXBasePaths::paths_iterator Path = Paths.begin(); Path != Paths.end(); ++Path) { @@ -2982,10 +2989,15 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (BaseType.isNull()) { BaseType = Context.getTypeDeclType(TyD); MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false); - if (SS.isSet()) - // FIXME: preserve source range information + if (SS.isSet()) { BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(), BaseType); + TInfo = Context.CreateTypeSourceInfo(BaseType); + ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>(); + TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + } } } @@ -3483,7 +3495,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/nullptr, MemberLookup, - /*TemplateArgs=*/nullptr); + /*TemplateArgs=*/nullptr, + /*S*/nullptr); if (CtorArg.isInvalid()) return true; @@ -4140,7 +4153,7 @@ static void DiagnoseBaseOrMemInitializerOrder( if (InitKey == IdealInitKeys[IdealIndex]) break; - assert(IdealIndex != NumIdealInits && + assert(IdealIndex < NumIdealInits && "initializer not found in initializer list"); } @@ -4407,64 +4420,35 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { } } -bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, - unsigned DiagID, AbstractDiagSelID SelID) { - class NonAbstractTypeDiagnoser : public TypeDiagnoser { - unsigned DiagID; - AbstractDiagSelID SelID; - - public: - NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID) - : TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { } - - void diagnose(Sema &S, SourceLocation Loc, QualType T) override { - if (Suppressed) return; - if (SelID == -1) - S.Diag(Loc, DiagID) << T; - else - S.Diag(Loc, DiagID) << SelID << T; - } - } Diagnoser(DiagID, SelID); - - return RequireNonAbstractType(Loc, T, Diagnoser); -} - -bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser) { +bool Sema::isAbstractType(SourceLocation Loc, QualType T) { if (!getLangOpts().CPlusPlus) return false; - if (const ArrayType *AT = Context.getAsArrayType(T)) - return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); - - if (const PointerType *PT = T->getAs<PointerType>()) { - // Find the innermost pointer type. - while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>()) - PT = T; - - if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) - return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); - } - - const RecordType *RT = T->getAs<RecordType>(); - if (!RT) + const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl(); + if (!RD) return false; - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + // FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a + // class template specialization here, but doing so breaks a lot of code. // We can't answer whether something is abstract until it has a - // definition. If it's currently being defined, we'll walk back + // definition. If it's currently being defined, we'll walk back // over all the declarations when we have a full definition. const CXXRecordDecl *Def = RD->getDefinition(); if (!Def || Def->isBeingDefined()) return false; - if (!RD->isAbstract()) + return RD->isAbstract(); +} + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + TypeDiagnoser &Diagnoser) { + if (!isAbstractType(Loc, T)) return false; + T = Context.getBaseElementType(T); Diagnoser.diagnose(*this, Loc, T); - DiagnoseAbstractType(RD); - + DiagnoseAbstractType(T->getAsCXXRecordDecl()); return true; } @@ -4684,6 +4668,60 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info, } } +static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { + Attr *ClassAttr = getDLLAttr(Class); + if (!ClassAttr) + return; + + assert(ClassAttr->getKind() == attr::DLLExport); + + TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); + + if (TSK == TSK_ExplicitInstantiationDeclaration) + // Don't go any further if this is just an explicit instantiation + // declaration. + return; + + for (Decl *Member : Class->decls()) { + auto *MD = dyn_cast<CXXMethodDecl>(Member); + if (!MD) + continue; + + if (Member->getAttr<DLLExportAttr>()) { + if (MD->isUserProvided()) { + // Instantiate non-default class member functions ... + + // .. except for certain kinds of template specializations. + if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) + continue; + + S.MarkFunctionReferenced(Class->getLocation(), MD); + + // The function will be passed to the consumer when its definition is + // encountered. + } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || + MD->isCopyAssignmentOperator() || + MD->isMoveAssignmentOperator()) { + // Synthesize and instantiate non-trivial implicit methods, explicitly + // 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. + DiagnosticErrorTrap Trap(S.Diags); + S.MarkFunctionReferenced(Class->getLocation(), MD); + if (Trap.hasErrorOccurred()) { + S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class) + << Class->getName() << !S.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)); + } + } + } +} + /// \brief Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); @@ -4785,45 +4823,10 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { NewAttr->setInherited(true); Member->addAttr(NewAttr); } - - if (MD && ClassExported) { - if (TSK == TSK_ExplicitInstantiationDeclaration) - // Don't go any further if this is just an explicit instantiation - // declaration. - continue; - - if (MD->isUserProvided()) { - // Instantiate non-default class member functions ... - - // .. except for certain kinds of template specializations. - if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) - continue; - - MarkFunctionReferenced(Class->getLocation(), MD); - - // The function will be passed to the consumer when its definition is - // encountered. - } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || - MD->isCopyAssignmentOperator() || - MD->isMoveAssignmentOperator()) { - // Synthesize and instantiate non-trivial implicit methods, explicitly - // 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. - 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. - Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); - } - } } + + if (ClassExported) + DelayedDllExportClasses.push_back(Class); } /// \brief Perform propagation of DLL attributes from a derived class to a @@ -5623,7 +5626,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( /// having a particular direct or virtual base class. bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl(); - return shouldDeleteForClassSubobject(BaseClass, Base, 0); + // If program is correct, BaseClass cannot be null, but if it is, the error + // must be reported elsewhere. + return BaseClass && shouldDeleteForClassSubobject(BaseClass, Base, 0); } /// Check whether we should delete a special member function due to the class @@ -6270,77 +6275,75 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, return true; } -/// \brief Data used with FindHiddenVirtualMethod namespace { - struct FindHiddenVirtualMethodData { - Sema *S; - CXXMethodDecl *Method; - llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods; - SmallVector<CXXMethodDecl *, 8> OverloadedMethods; - }; -} - -/// \brief Check whether any most overriden method from MD in Methods -static bool CheckMostOverridenMethods(const CXXMethodDecl *MD, - const llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) { - if (MD->size_overridden_methods() == 0) - return Methods.count(MD->getCanonicalDecl()); - for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), - E = MD->end_overridden_methods(); - I != E; ++I) - if (CheckMostOverridenMethods(*I, Methods)) - return true; - return false; -} +struct FindHiddenVirtualMethod { + Sema *S; + CXXMethodDecl *Method; + llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods; + SmallVector<CXXMethodDecl *, 8> OverloadedMethods; -/// \brief Member lookup function that determines whether a given C++ -/// method overloads virtual methods in a base class without overriding any, -/// to be used with CXXRecordDecl::lookupInBases(). -static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - void *UserData) { - RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); - - FindHiddenVirtualMethodData &Data - = *static_cast<FindHiddenVirtualMethodData*>(UserData); - - DeclarationName Name = Data.Method->getDeclName(); - assert(Name.getNameKind() == DeclarationName::Identifier); - - bool foundSameNameMethod = false; - SmallVector<CXXMethodDecl *, 8> overloadedMethods; - for (Path.Decls = BaseRecord->lookup(Name); - !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - NamedDecl *D = Path.Decls.front(); - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - MD = MD->getCanonicalDecl(); - foundSameNameMethod = true; - // Interested only in hidden virtual methods. - if (!MD->isVirtual()) - continue; - // If the method we are checking overrides a method from its base - // don't warn about the other overloaded methods. Clang deviates from GCC - // by only diagnosing overloads of inherited virtual functions that do not - // override any other virtual functions in the base. GCC's - // -Woverloaded-virtual diagnoses any derived function hiding a virtual - // function from a base class. These cases may be better served by a - // warning (not specific to virtual functions) on call sites when the call - // would select a different function from the base class, were it visible. - // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example. - if (!Data.S->IsOverload(Data.Method, MD, false)) +private: + /// Check whether any most overriden method from MD in Methods + static bool CheckMostOverridenMethods( + const CXXMethodDecl *MD, + const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) { + if (MD->size_overridden_methods() == 0) + return Methods.count(MD->getCanonicalDecl()); + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) + if (CheckMostOverridenMethods(*I, Methods)) return true; - // Collect the overload only if its hidden. - if (!CheckMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods)) - overloadedMethods.push_back(MD); - } + return false; } - if (foundSameNameMethod) - Data.OverloadedMethods.append(overloadedMethods.begin(), - overloadedMethods.end()); - return foundSameNameMethod; -} +public: + /// Member lookup function that determines whether a given C++ + /// method overloads virtual methods in a base class without overriding any, + /// to be used with CXXRecordDecl::lookupInBases(). + bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + RecordDecl *BaseRecord = + Specifier->getType()->getAs<RecordType>()->getDecl(); + + DeclarationName Name = Method->getDeclName(); + assert(Name.getNameKind() == DeclarationName::Identifier); + + bool foundSameNameMethod = false; + SmallVector<CXXMethodDecl *, 8> overloadedMethods; + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + NamedDecl *D = Path.Decls.front(); + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + MD = MD->getCanonicalDecl(); + foundSameNameMethod = true; + // Interested only in hidden virtual methods. + if (!MD->isVirtual()) + continue; + // If the method we are checking overrides a method from its base + // don't warn about the other overloaded methods. Clang deviates from + // GCC by only diagnosing overloads of inherited virtual functions that + // do not override any other virtual functions in the base. GCC's + // -Woverloaded-virtual diagnoses any derived function hiding a virtual + // function from a base class. These cases may be better served by a + // warning (not specific to virtual functions) on call sites when the + // call would select a different function from the base class, were it + // visible. + // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example. + if (!S->IsOverload(Method, MD, false)) + return true; + // Collect the overload only if its hidden. + if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods)) + overloadedMethods.push_back(MD); + } + } + + if (foundSameNameMethod) + OverloadedMethods.append(overloadedMethods.begin(), + overloadedMethods.end()); + return foundSameNameMethod; + } +}; +} // end anonymous namespace /// \brief Add the most overriden methods from MD to Methods static void AddMostOverridenMethods(const CXXMethodDecl *MD, @@ -6363,9 +6366,9 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases. /*bool RecordPaths=*/false, /*bool DetectVirtual=*/false); - FindHiddenVirtualMethodData Data; - Data.Method = MD; - Data.S = this; + FindHiddenVirtualMethod FHVM; + FHVM.Method = MD; + FHVM.S = this; // Keep the base methods that were overriden or introduced in the subclass // by 'using' in a set. A base method not in this set is hidden. @@ -6376,11 +6379,11 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I)) ND = shad->getTargetDecl(); if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) - AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods); + AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods); } - if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths)) - OverloadedMethods = Data.OverloadedMethods; + if (DC->lookupInBases(FHVM, Paths)) + OverloadedMethods = FHVM.OverloadedMethods; } void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD, @@ -6897,7 +6900,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, return Context.getFunctionType(Context.VoidTy, None, EPI); } -static void extendLeft(SourceRange &R, const SourceRange &Before) { +static void extendLeft(SourceRange &R, SourceRange Before) { if (Before.isInvalid()) return; R.setBegin(Before.getBegin()); @@ -6905,7 +6908,7 @@ static void extendLeft(SourceRange &R, const SourceRange &Before) { R.setEnd(Before.getEnd()); } -static void extendRight(SourceRange &R, const SourceRange &After) { +static void extendRight(SourceRange &R, SourceRange After) { if (After.isInvalid()) return; if (R.getBegin().isInvalid()) @@ -7019,7 +7022,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // If we can provide a correct fix-it hint, do so. if (After.isInvalid() && ConvTSI) { SourceLocation InsertLoc = - PP.getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd()); + getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd()); DB << FixItHint::CreateInsertion(InsertLoc, " ") << FixItHint::CreateInsertionFromRange( InsertLoc, CharSourceRange::getTokenRange(Before)) @@ -7102,7 +7105,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { if (ConvType == ClassType) Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used) << ClassType; - else if (IsDerivedFrom(ClassType, ConvType)) + else if (IsDerivedFrom(Conversion->getLocation(), ClassType, ConvType)) Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used) << ClassType << ConvType; } else if (ConvType->isVoidType()) { @@ -7169,7 +7172,8 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, - AttributeList *AttrList) { + AttributeList *AttrList, + UsingDirectiveDecl *&UD) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; @@ -7190,23 +7194,14 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // treated as an original-namespace-name. // // Since namespace names are unique in their scope, and we don't - // look through using directives, just look for any ordinary names. - - const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | - Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | - Decl::IDNS_Namespace; - NamedDecl *PrevDecl = nullptr; - DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; - ++I) { - if ((*I)->getIdentifierNamespace() & IDNS) { - PrevDecl = *I; - break; - } - } - + // look through using directives, just look for any ordinary names + // as if by qualified name lookup. + LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration); + LookupQualifiedName(R, CurContext->getRedeclContext()); + NamedDecl *PrevDecl = + R.isSingleResult() ? R.getRepresentativeDecl() : nullptr; PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl); - + if (PrevNS) { // This is an extended namespace definition. if (IsInline != PrevNS->isInline()) @@ -7293,14 +7288,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // namespace internal linkage. if (!PrevNS) { - UsingDirectiveDecl* UD - = UsingDirectiveDecl::Create(Context, Parent, - /* 'using' */ LBrace, - /* 'namespace' */ SourceLocation(), - /* qualifier */ NestedNameSpecifierLoc(), - /* identifier */ SourceLocation(), - Namespc, - /* Ancestor */ Parent); + UD = UsingDirectiveDecl::Create(Context, Parent, + /* 'using' */ LBrace, + /* 'namespace' */ SourceLocation(), + /* qualifier */ NestedNameSpecifierLoc(), + /* identifier */ SourceLocation(), + Namespc, + /* Ancestor */ Parent); UD->setImplicit(); Parent->addDecl(UD); } @@ -7538,7 +7532,7 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, S.PDiag(diag::err_using_directive_suggest) << Ident, S.PDiag(diag::note_namespace_defined_here)); } - R.addDecl(Corrected.getCorrectionDecl()); + R.addDecl(Corrected.getFoundDecl()); return true; } return false; @@ -7556,7 +7550,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, assert(IdentLoc.isValid() && "Invalid NamespceName location."); // This can only happen along a recovery path. - while (S->getFlags() & Scope::TemplateParamScope) + while (S->isTemplateParamScope()) S = S->getParent(); assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); @@ -7586,9 +7580,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S, } if (!R.empty()) { - NamedDecl *Named = R.getFoundDecl(); - assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named)) - && "expected namespace decl"); + NamedDecl *Named = R.getRepresentativeDecl(); + NamespaceDecl *NS = R.getAsSingle<NamespaceDecl>(); + assert(NS && "expected namespace decl"); // The use of a nested name specifier may trigger deprecation warnings. DiagnoseUseOfDecl(Named, IdentLoc); @@ -7605,7 +7599,6 @@ Decl *Sema::ActOnUsingDirective(Scope *S, // Find enclosing context containing both using-directive and // nominated namespace. - NamespaceDecl *NS = getNamespaceDecl(Named); DeclContext *CommonAncestor = cast<DeclContext>(NS); while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) CommonAncestor = CommonAncestor->getParent(); @@ -7805,7 +7798,8 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, FoundEquivalentDecl = true; } - (isa<TagDecl>(D) ? Tag : NonTag) = D; + if (isVisible(D)) + (isa<TagDecl>(D) ? Tag : NonTag) = D; } if (FoundEquivalentDecl) @@ -8014,6 +8008,10 @@ public: // FIXME: Check that the base class member is accessible? } + } else { + auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND); + if (FoundRecord && FoundRecord->isInjectedClassName()) + return false; } if (isa<TypeDecl>(ND)) @@ -8377,7 +8375,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, } else { // Convert 'using X::Y;' to 'typedef X::Y Y;'. SourceLocation InsertLoc = - PP.getLocForEndOfToken(NameInfo.getLocEnd()); + getLocForEndOfToken(NameInfo.getLocEnd()); Diag(InsertLoc, diag::note_using_decl_class_member_workaround) << 1 // typedef declaration << FixItHint::CreateReplacement(UsingLoc, "typedef") @@ -8470,40 +8468,26 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, // in the UsingDecl and UsingShadowDecl so that these checks didn't // need to be repeated. - struct UserData { - llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases; - - static bool collect(const CXXRecordDecl *Base, void *OpaqueData) { - UserData *Data = reinterpret_cast<UserData*>(OpaqueData); - Data->Bases.insert(Base); - return true; - } - - bool hasDependentBases(const CXXRecordDecl *Class) { - return !Class->forallBases(collect, this); - } - - /// Returns true if the base is dependent or is one of the - /// accumulated base classes. - static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) { - UserData *Data = reinterpret_cast<UserData*>(OpaqueData); - return !Data->Bases.count(Base); - } - - bool mightShareBases(const CXXRecordDecl *Class) { - return Bases.count(Class) || !Class->forallBases(doesNotContain, this); - } + llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases; + auto Collect = [&Bases](const CXXRecordDecl *Base) { + Bases.insert(Base); + return true; }; - UserData Data; - - // Returns false if we find a dependent base. - if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext))) + // Collect all bases. Return false if we find a dependent base. + if (!cast<CXXRecordDecl>(CurContext)->forallBases(Collect)) return false; - // Returns false if the class has a dependent base or if it or one + // Returns true if the base is dependent or is one of the accumulated base + // classes. + auto IsNotBase = [&Bases](const CXXRecordDecl *Base) { + return !Bases.count(Base); + }; + + // Return false if the class has a dependent base or if it or one // of its bases is present in the base set of the current context. - if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext))) + if (Bases.count(cast<CXXRecordDecl>(NamedContext)) || + !cast<CXXRecordDecl>(NamedContext)->forallBases(IsNotBase)) return false; Diag(SS.getRange().getBegin(), @@ -8524,7 +8508,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, TypeResult Type, Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. - while (S->getFlags() & Scope::TemplateParamScope) + while (S->isTemplateParamScope()) S = S->getParent(); assert((S->getFlags() & Scope::DeclScope) && "got alias-declaration outside of declaration scope"); @@ -8685,28 +8669,41 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, } } assert(!R.isAmbiguous() && !R.empty()); + NamedDecl *ND = R.getRepresentativeDecl(); // Check if we have a previous declaration with the same name. - NamedDecl *PrevDecl = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName, - ForRedeclaration); - if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) - PrevDecl = nullptr; + LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName, + ForRedeclaration); + LookupName(PrevR, S); - NamedDecl *ND = R.getFoundDecl(); + // Check we're not shadowing a template parameter. + if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl()); + PrevR.clear(); + } - if (PrevDecl) { + // Filter out any other lookup result from an enclosing scope. + FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false, + /*AllowInlineNamespace*/false); + + // Find the previous declaration and check that we can redeclare it. + NamespaceAliasDecl *Prev = nullptr; + if (PrevR.isSingleResult()) { + NamedDecl *PrevDecl = PrevR.getRepresentativeDecl(); if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) { // We already have an alias with the same name that points to the same // namespace; check that it matches. - if (!AD->getNamespace()->Equals(getNamespaceDecl(ND))) { + if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) { + Prev = AD; + } else if (isVisible(PrevDecl)) { Diag(AliasLoc, diag::err_redefinition_different_namespace_alias) << Alias; - Diag(PrevDecl->getLocation(), diag::note_previous_namespace_alias) + Diag(AD->getLocation(), diag::note_previous_namespace_alias) << AD->getNamespace(); return nullptr; } - } else { - unsigned DiagID = isa<NamespaceDecl>(PrevDecl) + } else if (isVisible(PrevDecl)) { + unsigned DiagID = isa<NamespaceDecl>(PrevDecl->getUnderlyingDecl()) ? diag::err_redefinition : diag::err_redefinition_different_kind; Diag(AliasLoc, DiagID) << Alias; @@ -8722,8 +8719,8 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, Alias, SS.getWithLocInContext(Context), IdentLoc, ND); - if (PrevDecl) - AliasDecl->setPreviousDecl(cast<NamespaceAliasDecl>(PrevDecl)); + if (Prev) + AliasDecl->setPreviousDecl(Prev); PushOnScopeChains(AliasDecl, S); return AliasDecl; @@ -9497,7 +9494,7 @@ static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) { } } -void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) { +void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { auto *RD = dyn_cast<CXXRecordDecl>(D); // Default constructors that are annotated with __declspec(dllexport) which @@ -9505,6 +9502,15 @@ void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) { // wrapped with a thunk called the default constructor closure. if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft()) getDefaultArgExprsForConstructors(*this, RD); + + if (!DelayedDllExportClasses.empty()) { + // Calling ReferenceDllExportedMethods might cause the current function to + // be called again, so use a local copy of DelayedDllExportClasses. + SmallVector<CXXRecordDecl *, 4> WorkList; + std::swap(DelayedDllExportClasses, WorkList); + for (CXXRecordDecl *Class : WorkList) + ReferenceDllExportedMethods(*this, Class); + } } void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, @@ -9618,7 +9624,7 @@ public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull(S.BuildMemberReferenceExpr( Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), - nullptr, MemberLookup, nullptr).get()); + nullptr, MemberLookup, nullptr, nullptr).get()); } MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow, @@ -9828,7 +9834,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, SS, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/nullptr, OpLookup, - /*TemplateArgs=*/nullptr, + /*TemplateArgs=*/nullptr, /*S*/nullptr, /*SuppressQualifierCheck=*/true); if (OpEqualRef.isInvalid()) return StmtError(); @@ -12207,7 +12213,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, diag::ext_unelaborated_friend_type) << (unsigned) RD->getTagKind() << T - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), + << FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc), InsertionText); } else { Diag(FriendLoc, @@ -12673,15 +12679,30 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, DC = CurContext; assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?"); } - + if (!DC->isRecord()) { + int DiagArg = -1; + switch (D.getName().getKind()) { + case UnqualifiedId::IK_ConstructorTemplateId: + case UnqualifiedId::IK_ConstructorName: + DiagArg = 0; + break; + case UnqualifiedId::IK_DestructorName: + DiagArg = 1; + break; + case UnqualifiedId::IK_ConversionFunctionId: + DiagArg = 2; + break; + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_ImplicitSelfParam: + case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_TemplateId: + break; + } // This implies that it has to be an operator or function. - if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName || - D.getName().getKind() == UnqualifiedId::IK_DestructorName || - D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) { - Diag(Loc, diag::err_introducing_special_friend) << - (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 : - D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2); + if (DiagArg >= 0) { + Diag(Loc, diag::err_introducing_special_friend) << DiagArg; return nullptr; } } @@ -12983,7 +13004,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { // Check if the new class derives from the old class. - if (!IsDerivedFrom(NewClassTy, OldClassTy)) { + if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) { Diag(New->getLocation(), diag::err_covariant_return_not_derived) << New->getDeclName() << NewTy << OldTy << New->getReturnTypeSourceRange(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index f42c4b7..a2f41a7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -15,12 +15,11 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" -#include "clang/AST/DataRecursiveASTVisitor.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" #include "clang/Basic/SourceManager.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Lookup.h" @@ -100,9 +99,8 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method, // If we're in a system header, and this is not a call, just make // the method unusable. if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) { - method->addAttr(UnavailableAttr::CreateImplicit(Context, - "init method returns a type unrelated to its receiver type", - loc)); + method->addAttr(UnavailableAttr::CreateImplicit(Context, "", + UnavailableAttr::IR_ARCInitReturnsUnrelated, loc)); return true; } @@ -449,7 +447,7 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { ObjCInterfaceDecl *CurrentIDecl; }; -} +} // end anonymous namespace static void diagnoseUseOfProtocols(Sema &TheSema, ObjCContainerDecl *CD, @@ -484,7 +482,7 @@ ActOnSuperClassOfClassInterface(Scope *S, if (TypoCorrection Corrected = CorrectTypo( DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope, - NULL, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl), + nullptr, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl), CTK_ErrorRecovery)) { diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest) << SuperName << ClassName); @@ -507,7 +505,7 @@ ActOnSuperClassOfClassInterface(Scope *S, SuperClassType = Context.getObjCInterfaceType(SuperClassDecl); } - if (PrevDecl && SuperClassDecl == 0) { + if (PrevDecl && !SuperClassDecl) { // The previous declaration was not a class decl. Check if we have a // typedef. If we do, get the underlying class type. if (const TypedefNameDecl *TDecl = @@ -548,7 +546,7 @@ ActOnSuperClassOfClassInterface(Scope *S, SuperClassDecl->getDeclName(), ClassName, SourceRange(AtInterfaceLoc, ClassLoc))) { - SuperClassDecl = 0; + SuperClassDecl = nullptr; SuperClassType = QualType(); } } @@ -608,7 +606,7 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, } else if (typeBound->isObjCObjectType()) { // The user forgot the * on an Objective-C pointer type, e.g., // "T : NSView". - SourceLocation starLoc = PP.getLocForEndOfToken( + SourceLocation starLoc = getLocForEndOfToken( typeBoundInfo->getTypeLoc().getEndLoc()); Diag(typeBoundInfo->getTypeLoc().getBeginLoc(), diag::err_objc_type_param_bound_missing_pointer) @@ -638,20 +636,44 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, typeBoundInfo = nullptr; } - // Type bounds cannot have explicit nullability. + // Type bounds cannot have qualifiers (even indirectly) or explicit + // nullability. if (typeBoundInfo) { - // Type arguments cannot explicitly specify nullability. - if (auto nullability = AttributedType::stripOuterNullability(typeBound)) { - // Look at the type location information to find the nullability - // specifier so we can zap it. - SourceLocation nullabilityLoc - = typeBoundInfo->getTypeLoc().findNullabilityLoc(); - SourceLocation diagLoc - = nullabilityLoc.isValid()? nullabilityLoc - : typeBoundInfo->getTypeLoc().getLocStart(); - Diag(diagLoc, diag::err_type_param_bound_explicit_nullability) - << paramName << typeBoundInfo->getType() - << FixItHint::CreateRemoval(nullabilityLoc); + QualType typeBound = typeBoundInfo->getType(); + TypeLoc qual = typeBoundInfo->getTypeLoc().findExplicitQualifierLoc(); + if (qual || typeBound.hasQualifiers()) { + bool diagnosed = false; + SourceRange rangeToRemove; + if (qual) { + if (auto attr = qual.getAs<AttributedTypeLoc>()) { + rangeToRemove = attr.getLocalSourceRange(); + if (attr.getTypePtr()->getImmediateNullability()) { + Diag(attr.getLocStart(), + diag::err_objc_type_param_bound_explicit_nullability) + << paramName << typeBound + << FixItHint::CreateRemoval(rangeToRemove); + diagnosed = true; + } + } + } + + if (!diagnosed) { + Diag(qual ? qual.getLocStart() + : typeBoundInfo->getTypeLoc().getLocStart(), + diag::err_objc_type_param_bound_qualified) + << paramName << typeBound << typeBound.getQualifiers().getAsString() + << FixItHint::CreateRemoval(rangeToRemove); + } + + // If the type bound has qualifiers other than CVR, we need to strip + // them or we'll probably assert later when trying to apply new + // qualifiers. + Qualifiers quals = typeBound.getQualifiers(); + quals.removeCVRQualifiers(); + if (!quals.empty()) { + typeBoundInfo = + Context.getTrivialTypeSourceInfo(typeBound.getUnqualifiedType()); + } } } } @@ -722,7 +744,7 @@ namespace { Category, Extension }; -} +} // end anonymous namespace /// Check consistency between two Objective-C type parameter lists, e.g., /// between a category/extension and an \@interface or between an \@class and an @@ -737,7 +759,7 @@ static bool checkTypeParamListConsistency(Sema &S, if (newTypeParams->size() > prevTypeParams->size()) { diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation(); } else { - diagLoc = S.PP.getLocForEndOfToken(newTypeParams->back()->getLocEnd()); + diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getLocEnd()); } S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch) @@ -852,7 +874,7 @@ static bool checkTypeParamListConsistency(Sema &S, newContext == TypeParamListContext::Definition) { // Diagnose this problem for forward declarations and definitions. SourceLocation insertionLoc - = S.PP.getLocForEndOfToken(newTypeParam->getLocation()); + = S.getLocForEndOfToken(newTypeParam->getLocation()); std::string newCode = " : " + prevTypeParam->getUnderlyingType().getAsString( S.Context.getPrintingPolicy()); @@ -1184,26 +1206,23 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl, /// protocol declarations in its 'Protocols' argument. void Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, - const IdentifierLocPair *ProtocolId, - unsigned NumProtocols, + ArrayRef<IdentifierLocPair> ProtocolId, SmallVectorImpl<Decl *> &Protocols) { - for (unsigned i = 0; i != NumProtocols; ++i) { - ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first, - ProtocolId[i].second); + for (const IdentifierLocPair &Pair : ProtocolId) { + ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second); if (!PDecl) { TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second), + DeclarationNameInfo(Pair.first, Pair.second), LookupObjCProtocolName, TUScope, nullptr, llvm::make_unique<DeclFilterCCC<ObjCProtocolDecl>>(), CTK_ErrorRecovery); if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest) - << ProtocolId[i].first); + << Pair.first); } if (!PDecl) { - Diag(ProtocolId[i].second, diag::err_undeclared_protocol) - << ProtocolId[i].first; + Diag(Pair.second, diag::err_undeclared_protocol) << Pair.first; continue; } // If this is a forward protocol declaration, get its definition. @@ -1213,7 +1232,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, // 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); + (void)DiagnoseUseOfDecl(PDecl, Pair.second); } // If this is a forward declaration and we are supposed to warn in this @@ -1223,8 +1242,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, if (WarnOnDeclarations && NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) { - Diag(ProtocolId[i].second, diag::warn_undef_protocolref) - << ProtocolId[i].first; + Diag(Pair.second, diag::warn_undef_protocolref) << Pair.first; Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined) << UndefinedProtocol; } @@ -1388,8 +1406,8 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( if (allProtocolsDeclared) { Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type) << baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc) - << FixItHint::CreateInsertion( - PP.getLocForEndOfToken(firstClassNameLoc), " *"); + << FixItHint::CreateInsertion(getLocForEndOfToken(firstClassNameLoc), + " *"); } } @@ -1469,15 +1487,15 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // If we have a typedef of an Objective-C class type that is missing a '*', // add the '*'. if (type->getAs<ObjCInterfaceType>()) { - SourceLocation starLoc = PP.getLocForEndOfToken(loc); + SourceLocation starLoc = getLocForEndOfToken(loc); ParsedAttributes parsedAttrs(attrFactory); D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc, SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation()), - parsedAttrs, - starLoc); + parsedAttrs, + starLoc); // Diagnose the missing '*'. Diag(loc, diag::err_objc_type_arg_missing_star) @@ -1655,17 +1673,16 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, /// ActOnForwardProtocolDeclaration - Handle \@protocol foo; Sema::DeclGroupPtrTy Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, - const IdentifierLocPair *IdentList, - unsigned NumElts, + ArrayRef<IdentifierLocPair> IdentList, AttributeList *attrList) { SmallVector<Decl *, 8> DeclsInGroup; - for (unsigned i = 0; i != NumElts; ++i) { - IdentifierInfo *Ident = IdentList[i].first; - ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentList[i].second, + for (const IdentifierLocPair &IdentPair : IdentList) { + IdentifierInfo *Ident = IdentPair.first; + ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentPair.second, ForRedeclaration); ObjCProtocolDecl *PDecl = ObjCProtocolDecl::Create(Context, CurContext, Ident, - IdentList[i].second, AtProtocolLoc, + IdentPair.second, AtProtocolLoc, PrevDecl); PushOnScopeChains(PDecl, TUScope); @@ -1850,6 +1867,8 @@ Decl *Sema::ActOnStartClassImplementation( Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) { + // FIXME: This will produce an error if the definition of the interface has + // been imported from a module but is not visible. RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), diag::warn_undef_interface); } else { @@ -2247,7 +2266,7 @@ static bool CheckMethodOverrideReturn(Sema &S, DiagID = IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types - : diag::warn_non_covariant_ret_types; + : diag::warn_non_covariant_ret_types; } } @@ -2331,7 +2350,7 @@ static bool CheckMethodOverrideParam(Sema &S, DiagID = IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types - : diag::warn_non_contravariant_param_types; + : diag::warn_non_contravariant_param_types; } } @@ -2340,7 +2359,7 @@ static bool CheckMethodOverrideParam(Sema &S, << MethodImpl->getDeclName() << IfaceTy << ImplTy; S.Diag(IfaceVar->getLocation(), (IsOverridingMode ? diag::note_previous_declaration - : diag::note_previous_definition)) + : diag::note_previous_definition)) << getTypeRange(IfaceVar->getTypeSourceInfo()); return false; } @@ -2749,7 +2768,8 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, if (!WarnCategoryMethodImpl) { for (auto *Cat : I->visible_categories()) MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, - IMPDecl, Cat, IncompleteImpl, false, + IMPDecl, Cat, IncompleteImpl, + ImmediateClass && Cat->IsClassExtension(), WarnCategoryMethodImpl); } else { // Also methods in class extensions need be looked at next. @@ -2825,6 +2845,20 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, for (const auto *I : IMPDecl->instance_methods()) InsMap.insert(I->getSelector()); + // Add the selectors for getters/setters of @dynamic properties. + for (const auto *PImpl : IMPDecl->property_impls()) { + // We only care about @dynamic implementations. + if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic) + continue; + + const auto *P = PImpl->getPropertyDecl(); + if (!P) continue; + + InsMap.insert(P->getGetterName()); + if (!P->getSetterName().isNull()) + InsMap.insert(P->getSetterName()); + } + // Check and see if properties declared in the interface have either 1) // an implementation or 2) there is a @synthesize/@dynamic implementation // of the property in the @implementation. @@ -2866,9 +2900,6 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, for (auto *PI : I->all_referenced_protocols()) CheckProtocolMethodDefs(*this, IMPDecl->getLocation(), PI, IncompleteImpl, InsMap, ClsMap, I, ExplicitImplProtocols); - // Check class extensions (unnamed categories) - for (auto *Ext : I->visible_extensions()) - ImplMethodsVsClassMethods(S, IMPDecl, Ext, IncompleteImpl); } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { // For extended class, unimplemented methods in its protocols will // be reported in the primary class. @@ -3478,6 +3509,23 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, } } +/// Diagnose attempts to define ARC-__weak ivars when __weak is disabled. +static void DiagnoseWeakIvars(Sema &S, ObjCImplementationDecl *ID) { + if (S.getLangOpts().ObjCWeak) return; + + for (auto ivar = ID->getClassInterface()->all_declared_ivar_begin(); + ivar; ivar = ivar->getNextIvar()) { + if (ivar->isInvalidDecl()) continue; + if (ivar->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { + if (S.getLangOpts().ObjCWeakRuntime) { + S.Diag(ivar->getLocation(), diag::err_arc_weak_disabled); + } else { + S.Diag(ivar->getLocation(), diag::err_arc_weak_no_runtime); + } + } + } +} + Sema::ObjCContainerKind Sema::getObjCContainerKind() const { switch (CurContext->getDeclKind()) { case Decl::ObjCInterface: @@ -3590,7 +3638,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, // user-defined setter/getter. It also synthesizes setter/getter methods // and adds them to the DeclContext and global method pools. for (auto *I : CDecl->properties()) - ProcessPropertyDecl(I, CDecl); + ProcessPropertyDecl(I); CDecl->setAtEndRange(AtEnd); } if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) { @@ -3627,6 +3675,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, DiagnoseUnusedBackingIvarInAccessor(S, IC); if (IDecl->hasDesignatedInitializers()) DiagnoseMissingDesignatedInitOverrides(IC, IDecl); + DiagnoseWeakIvars(*this, IC); bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>(); if (IDecl->getSuperClass() == nullptr) { @@ -3700,7 +3749,6 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, return ClassDecl; } - /// CvtQTToAstBitMask - utility routine to produce an AST bitmask for /// objective-c's type qualifier from the parser version of the same info. static Decl::ObjCDeclQualifier @@ -3867,7 +3915,6 @@ private: search(Interface); } - void search(const ObjCProtocolList &protocols) { for (ObjCProtocolList::iterator i = protocols.begin(), e = protocols.end(); i != e; ++i) @@ -3895,7 +3942,7 @@ private: searchFromContainer(container); } }; -} +} // end anonymous namespace void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, ObjCInterfaceDecl *CurrentClass, @@ -4490,7 +4537,6 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { if (!LookupImplementedMethodInGlobalPool(Sel)) Diag(Loc, diag::warn_unimplemented_selector) << Sel; } - return; } ObjCIvarDecl * @@ -4522,7 +4568,7 @@ namespace { /// Used by Sema::DiagnoseUnusedBackingIvarInAccessor to check if a property /// accessor references the backing ivar. class UnusedBackingIvarChecker : - public DataRecursiveASTVisitor<UnusedBackingIvarChecker> { + public RecursiveASTVisitor<UnusedBackingIvarChecker> { public: Sema &S; const ObjCMethodDecl *Method; @@ -4553,7 +4599,7 @@ namespace { return true; } }; -} +} // end anonymous namespace void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S, const ObjCImplementationDecl *ImplD) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp index 2cf02b4..f12bf24 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -68,7 +68,7 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) { /// /// \param[in,out] T The exception type. This will be decayed to a pointer type /// when the input is an array or a function type. -bool Sema::CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range) { +bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { // C++11 [except.spec]p2: // A type cv T, "array of T", or "function returning T" denoted // in an exception-specification is adjusted to type T, "pointer to T", or @@ -232,7 +232,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) { Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch) << hasImplicitExceptionSpec(Old); - if (!Old->getLocation().isInvalid()) + if (Old->getLocation().isValid()) Diag(Old->getLocation(), diag::note_previous_declaration); } return false; @@ -270,16 +270,35 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType(); if (ESI.Type == EST_Dynamic) { ESI.Exceptions = OldProto->exceptions(); - } else if (ESI.Type == EST_ComputedNoexcept) { - // FIXME: We can't just take the expression from the old prototype. It - // likely contains references to the old prototype's parameters. } - // Update the type of the function with the appropriate exception - // specification. - New->setType(Context.getFunctionType( - NewProto->getReturnType(), NewProto->getParamTypes(), - NewProto->getExtProtoInfo().withExceptionSpec(ESI))); + if (ESI.Type == EST_ComputedNoexcept) { + // For computed noexcept, we can't just take the expression from the old + // prototype. It likely contains references to the old prototype's + // parameters. + New->setInvalidDecl(); + } else { + // Update the type of the function with the appropriate exception + // specification. + New->setType(Context.getFunctionType( + NewProto->getReturnType(), NewProto->getParamTypes(), + NewProto->getExtProtoInfo().withExceptionSpec(ESI))); + } + + if (getLangOpts().MicrosoftExt && ESI.Type != EST_ComputedNoexcept) { + // Allow missing exception specifications in redeclarations as an extension. + DiagID = diag::ext_ms_missing_exception_specification; + ReturnValueOnError = false; + } else if (New->isReplaceableGlobalAllocationFunction() && + ESI.Type != EST_ComputedNoexcept) { + // Allow missing exception specifications in redeclarations as an extension, + // when declaring a replaceable global allocation function. + DiagID = diag::ext_missing_exception_specification; + ReturnValueOnError = false; + } else { + DiagID = diag::err_missing_exception_specification; + ReturnValueOnError = true; + } // Warn about the lack of exception specification. SmallString<128> ExceptionSpecString; @@ -318,30 +337,30 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { default: llvm_unreachable("This spec type is compatible with none."); } - OS.flush(); SourceLocation FixItLoc; if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); - if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>()) - FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd()); + // FIXME: Preserve enough information so that we can produce a correct fixit + // location when there is a trailing return type. + if (auto FTLoc = TL.getAs<FunctionProtoTypeLoc>()) + if (!FTLoc.getTypePtr()->hasTrailingReturn()) + FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd()); } if (FixItLoc.isInvalid()) - Diag(New->getLocation(), diag::warn_missing_exception_specification) + Diag(New->getLocation(), DiagID) << New << OS.str(); else { - // FIXME: This will get more complicated with C++0x - // late-specified return types. - Diag(New->getLocation(), diag::warn_missing_exception_specification) + Diag(New->getLocation(), DiagID) << New << OS.str() << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); } - if (!Old->getLocation().isInvalid()) + if (Old->getLocation().isValid()) Diag(Old->getLocation(), diag::note_previous_declaration); - return false; + return ReturnValueOnError; } /// CheckEquivalentExceptionSpec - Check if the two types have equivalent @@ -694,7 +713,7 @@ bool Sema::CheckExceptionSpecSubset( continue; Paths.clear(); - if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths)) + if (!IsDerivedFrom(SubLoc, CanonicalSubT, CanonicalSuperT, Paths)) continue; if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT))) @@ -979,8 +998,9 @@ CanThrowResult Sema::canThrow(const Expr *E) { case Expr::LambdaExprClass: { const LambdaExpr *Lambda = cast<LambdaExpr>(E); CanThrowResult CT = CT_Cannot; - for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(), - CapEnd = Lambda->capture_init_end(); + for (LambdaExpr::const_capture_init_iterator + Cap = Lambda->capture_init_begin(), + CapEnd = Lambda->capture_init_end(); Cap != CapEnd; ++Cap) CT = mergeCanThrow(CT, canThrow(*Cap)); return CT; @@ -1043,8 +1063,10 @@ CanThrowResult Sema::canThrow(const Expr *E) { // Many other things have subexpressions, so we have to test those. // Some are simple: + case Expr::CoawaitExprClass: case Expr::ConditionalOperatorClass: case Expr::CompoundLiteralExprClass: + case Expr::CoyieldExprClass: case Expr::CXXConstCastExprClass: case Expr::CXXReinterpretCastExprClass: case Expr::CXXStdInitializerListExprClass: @@ -1065,6 +1087,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { // Some might be dependent for other reasons. case Expr::ArraySubscriptExprClass: + case Expr::OMPArraySectionExprClass: case Expr::BinaryOperatorClass: case Expr::CompoundAssignOperatorClass: case Expr::CStyleCastExprClass: @@ -1156,6 +1179,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { return CT_Cannot; case Expr::MSPropertyRefExprClass: + case Expr::MSPropertySubscriptExprClass: llvm_unreachable("Invalid class for expression"); #define STMT(CLASS, PARENT) case Expr::CLASS##Class: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 6499cb5..5d0c605 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -24,6 +24,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/PartialDiagnostic.h" @@ -326,18 +327,16 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) { // If there were any diagnostics suppressed by template argument deduction, // emit them now. - SuppressedDiagnosticsMap::iterator - Pos = SuppressedDiagnostics.find(D->getCanonicalDecl()); + auto Pos = SuppressedDiagnostics.find(D->getCanonicalDecl()); if (Pos != SuppressedDiagnostics.end()) { - SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second; - for (unsigned I = 0, N = Suppressed.size(); I != N; ++I) - Diag(Suppressed[I].first, Suppressed[I].second); + for (const PartialDiagnosticAt &Suppressed : Pos->second) + Diag(Suppressed.first, Suppressed.second); // Clear out the list of suppressed diagnostics, so that we don't emit // them again for this specialization. However, we don't obsolete this // entry from the table, because we want to avoid ever emitting these // diagnostics again. - Suppressed.clear(); + Pos->second.clear(); } // C++ [basic.start.main]p3: @@ -348,8 +347,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, // See if this is an auto-typed variable whose initializer we are parsing. if (ParsingInitForAutoVars.count(D)) { + const AutoType *AT = cast<VarDecl>(D)->getType()->getContainedAutoType(); + Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer) - << D->getDeclName(); + << D->getDeclName() << (unsigned)AT->getKeyword(); return true; } @@ -464,7 +465,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, // 'nil' for ObjC methods, where it's much more likely that the // variadic arguments form a list of object pointers. SourceLocation MissingNilLoc - = PP.getLocForEndOfToken(sentinelExpr->getLocEnd()); + = getLocForEndOfToken(sentinelExpr->getLocEnd()); std::string NullValue; if (calleeType == CT_Method && PP.isMacroDefined("nil")) NullValue = "nil"; @@ -493,7 +494,7 @@ SourceRange Sema::getExprRange(Expr *E) const { //===----------------------------------------------------------------------===// /// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4). -ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) { +ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) { // Handle any placeholder expressions which made it here. if (E->getType()->isPlaceholderType()) { ExprResult result = CheckPlaceholderExpr(E); @@ -508,9 +509,16 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) { // If we are here, we are not calling a function but taking // its address (which is not allowed in OpenCL v1.0 s6.8.a.3). if (getLangOpts().OpenCL) { - Diag(E->getExprLoc(), diag::err_opencl_taking_function_address); + if (Diagnose) + Diag(E->getExprLoc(), diag::err_opencl_taking_function_address); return ExprError(); } + + if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts())) + if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) + if (!checkAddressOfFunctionIsAvailable(FD, Diagnose, E->getExprLoc())) + return ExprError(); + E = ImpCastExprToType(E, Context.getPointerType(Ty), CK_FunctionToPointerDecay).get(); } else if (Ty->isArrayType()) { @@ -579,7 +587,7 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE, &S.Context.Idents.get("object_setClass"), SourceLocation(), S.LookupOrdinaryName); if (ObjectSetClass) { - SourceLocation RHSLocEnd = S.PP.getLocForEndOfToken(RHS->getLocEnd()); + SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getLocEnd()); S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign) << FixItHint::CreateInsertion(OIRE->getLocStart(), "object_setClass(") << FixItHint::CreateReplacement(SourceRange(OIRE->getOpLoc(), @@ -676,6 +684,11 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (T.hasQualifiers()) T = T.getUnqualifiedType(); + // Under the MS ABI, lock down the inheritance model now. + if (T->isMemberPointerType() && + Context.getTargetInfo().getCXXABI().isMicrosoft()) + (void)isCompleteType(E->getExprLoc(), T); + UpdateMarkingForLValueToRValue(E); // Loading a __weak object implicitly retains the value, so we need a cleanup to @@ -699,8 +712,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { return Res; } -ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) { - ExprResult Res = DefaultFunctionArrayConversion(E); +ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose) { + ExprResult Res = DefaultFunctionArrayConversion(E, Diagnose); if (Res.isInvalid()) return ExprError(); Res = DefaultLvalueConversion(Res.get()); @@ -1349,11 +1362,13 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, ArrayRef<Expr *> Exprs) { unsigned NumAssocs = Types.size(); assert(NumAssocs == Exprs.size()); - if (ControllingExpr->getType()->isPlaceholderType()) { - ExprResult result = CheckPlaceholderExpr(ControllingExpr); - if (result.isInvalid()) return ExprError(); - ControllingExpr = result.get(); - } + + // Decay and strip qualifiers for the controlling expression type, and handle + // placeholder type replacement. See committee discussion from WG14 DR423. + ExprResult R = DefaultFunctionArrayLvalueConversion(ControllingExpr); + if (R.isInvalid()) + return ExprError(); + ControllingExpr = R.get(); // The controlling expression is an unevaluated operand, so side effects are // likely unintended. @@ -1445,12 +1460,11 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match) << ControllingExpr->getSourceRange() << ControllingExpr->getType() << (unsigned) CompatIndices.size(); - for (SmallVectorImpl<unsigned>::iterator I = CompatIndices.begin(), - E = CompatIndices.end(); I != E; ++I) { - Diag(Types[*I]->getTypeLoc().getBeginLoc(), + for (unsigned I : CompatIndices) { + Diag(Types[I]->getTypeLoc().getBeginLoc(), diag::note_compat_assoc) - << Types[*I]->getTypeLoc().getSourceRange() - << Types[*I]->getType(); + << Types[I]->getTypeLoc().getSourceRange() + << Types[I]->getType(); } return ExprError(); } @@ -1533,8 +1547,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { return ExprError(); SmallVector<SourceLocation, 4> StringTokLocs; - for (unsigned i = 0; i != StringToks.size(); ++i) - StringTokLocs.push_back(StringToks[i].getLocation()); + for (const Token &Tok : StringToks) + StringTokLocs.push_back(Tok.getLocation()); QualType CharTy = Context.CharTy; StringLiteral::StringKind Kind = StringLiteral::Ascii; @@ -1697,7 +1711,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, MarkDeclRefReferenced(E); - if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) && + if (getLangOpts().ObjCWeak && isa<VarDecl>(D) && Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) recordUseOfEvaluatedWeak(E); @@ -1762,10 +1776,9 @@ static void emitEmptyLookupTypoDiagnostic( std::string CorrectedStr = TC.getAsString(SemaRef.getLangOpts()); bool DroppedSpecifier = TC.WillReplaceSpecifier() && Typo.getAsString() == CorrectedStr; - unsigned NoteID = - (TC.getCorrectionDecl() && isa<ImplicitParamDecl>(TC.getCorrectionDecl())) - ? diag::note_implicit_param_decl - : diag::note_previous_decl; + unsigned NoteID = TC.getCorrectionDeclAs<ImplicitParamDecl>() + ? diag::note_implicit_param_decl + : diag::note_previous_decl; if (!Ctx) SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo, SemaRef.PDiag(NoteID)); @@ -1799,8 +1812,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // unqualified lookup. This is useful when (for example) the // original lookup would not have found something because it was a // dependent name. - DeclContext *DC = (SS.isEmpty() && !CallsUndergoingInstantiation.empty()) - ? CurContext : nullptr; + DeclContext *DC = SS.isEmpty() ? CurContext : nullptr; while (DC) { if (isa<CXXRecordDecl>(DC)) { LookupQualifiedName(R, DC); @@ -1819,7 +1831,6 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, bool isInstance = CurMethod && CurMethod->isInstance() && DC == CurMethod->getParent() && !isDefaultArgument; - // Give a code modification hint to insert 'this->'. // TODO: fixit for inserting 'Base<T>::' in the other cases. @@ -1829,46 +1840,14 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, if (isInstance) { Diag(R.getNameLoc(), diagnostic) << Name << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); - UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>( - CallsUndergoingInstantiation.back()->getCallee()); - - CXXMethodDecl *DepMethod; - if (CurMethod->isDependentContext()) - DepMethod = CurMethod; - else if (CurMethod->getTemplatedKind() == - FunctionDecl::TK_FunctionTemplateSpecialization) - DepMethod = cast<CXXMethodDecl>(CurMethod->getPrimaryTemplate()-> - getInstantiatedFromMemberTemplate()->getTemplatedDecl()); - else - DepMethod = cast<CXXMethodDecl>( - CurMethod->getInstantiatedFromMemberFunction()); - assert(DepMethod && "No template pattern found"); - - QualType DepThisType = DepMethod->getThisType(Context); CheckCXXThisCapture(R.getNameLoc()); - CXXThisExpr *DepThis = new (Context) CXXThisExpr( - R.getNameLoc(), DepThisType, false); - TemplateArgumentListInfo TList; - if (ULE->hasExplicitTemplateArgs()) - ULE->copyTemplateArgumentsInto(TList); - - CXXScopeSpec SS; - SS.Adopt(ULE->getQualifierLoc()); - CXXDependentScopeMemberExpr *DepExpr = - CXXDependentScopeMemberExpr::Create( - Context, DepThis, DepThisType, true, SourceLocation(), - SS.getWithLocInContext(Context), - ULE->getTemplateKeywordLoc(), nullptr, - R.getLookupNameInfo(), - ULE->hasExplicitTemplateArgs() ? &TList : nullptr); - CallsUndergoingInstantiation.back()->setCallee(DepExpr); } else { Diag(R.getNameLoc(), diagnostic) << Name; } // Do we really want to note all of these? - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - Diag((*I)->getLocation(), diag::note_dependent_var_use); + for (NamedDecl *D : R) + Diag(D->getLocation(), diag::note_dependent_var_use); // Return true if we are inside a default argument instantiation // and the found name refers to an instance member function, otherwise @@ -1923,28 +1902,26 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, bool AcceptableWithRecovery = false; bool AcceptableWithoutRecovery = false; - NamedDecl *ND = Corrected.getCorrectionDecl(); + NamedDecl *ND = Corrected.getFoundDecl(); if (ND) { if (Corrected.isOverloaded()) { OverloadCandidateSet OCS(R.getNameLoc(), OverloadCandidateSet::CSK_Normal); OverloadCandidateSet::iterator Best; - for (TypoCorrection::decl_iterator CD = Corrected.begin(), - CDEnd = Corrected.end(); - CD != CDEnd; ++CD) { + for (NamedDecl *CD : Corrected) { if (FunctionTemplateDecl *FTD = - dyn_cast<FunctionTemplateDecl>(*CD)) + dyn_cast<FunctionTemplateDecl>(CD)) AddTemplateOverloadCandidate( FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs, Args, OCS); - else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD)) + else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0) AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args, OCS); } switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) { case OR_Success: - ND = Best->Function; + ND = Best->FoundDecl; Corrected.setCorrectionDecl(ND); break; default: @@ -1966,15 +1943,16 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, R.setNamingClass(Record); } - AcceptableWithRecovery = - isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND); + auto *UnderlyingND = ND->getUnderlyingDecl(); + AcceptableWithRecovery = isa<ValueDecl>(UnderlyingND) || + isa<FunctionTemplateDecl>(UnderlyingND); // FIXME: If we ended up with a typo for a type name or // Objective-C class name, we're in trouble because the parser // is in the wrong place to recover. Suggest the typo // correction, but don't make it a fix-it since we're not going // to recover well anyway. AcceptableWithoutRecovery = - isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); + isa<TypeDecl>(UnderlyingND) || isa<ObjCInterfaceDecl>(UnderlyingND); } else { // FIXME: We found a keyword. Suggest it, but don't provide a fix-it // because we aren't able to recover. @@ -1982,8 +1960,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, } if (AcceptableWithRecovery || AcceptableWithoutRecovery) { - unsigned NoteID = (Corrected.getCorrectionDecl() && - isa<ImplicitParamDecl>(Corrected.getCorrectionDecl())) + unsigned NoteID = Corrected.getCorrectionDeclAs<ImplicitParamDecl>() ? diag::note_implicit_param_decl : diag::note_previous_decl; if (SS.isEmpty()) @@ -2278,7 +2255,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, if (MightBeImplicitMember) return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, - R, TemplateArgs); + R, TemplateArgs, S); } if (TemplateArgs || TemplateKWLoc.isValid()) { @@ -2302,11 +2279,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, /// declaration name, generally during template instantiation. /// There's a large number of things which don't need to be done along /// this path. -ExprResult -Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, - bool IsAddressOfOperand, - TypeSourceInfo **RecoveryTSI) { +ExprResult Sema::BuildQualifiedDeclarationNameExpr( + CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, + bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { DeclContext *DC = computeDeclContext(SS, false); if (!DC) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), @@ -2373,7 +2348,7 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand) return BuildPossibleImplicitMemberExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - R, /*TemplateArgs=*/nullptr); + R, /*TemplateArgs=*/nullptr, S); return BuildDeclarationNameExpr(SS, R, /* ADL */ false); } @@ -2615,7 +2590,7 @@ Sema::PerformObjectMemberConversion(Expr *From, // In C++98, the qualifier type doesn't actually have to be a base // type of the object type, in which case we just ignore it. // Otherwise build the appropriate casts. - if (IsDerivedFrom(FromRecordType, QRecordType)) { + if (IsDerivedFrom(FromLoc, FromRecordType, QRecordType)) { CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, QRecordType, FromLoc, FromRange, &BasePath)) @@ -2651,7 +2626,7 @@ Sema::PerformObjectMemberConversion(Expr *From, // We only need to do this if the naming-class to declaring-class // conversion is non-trivial. if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) { - assert(IsDerivedFrom(FromRecordType, URecordType)); + assert(IsDerivedFrom(FromLoc, FromRecordType, URecordType)); CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, URecordType, FromLoc, FromRange, &BasePath)) @@ -2698,9 +2673,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, // Turn off ADL when we find certain kinds of declarations during // normal lookup: - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { - NamedDecl *D = *I; - + for (NamedDecl *D : R) { // C++0x [basic.lookup.argdep]p3: // -- a declaration of a class member // Since using decls preserve this property, we check this on the @@ -3355,13 +3328,6 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // Get the value in the widest-possible width. unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth(); - // The microsoft literal suffix extensions support 128-bit literals, which - // may be wider than [u]intmax_t. - // FIXME: Actually, they don't. We seem to have accidentally invented the - // i128 suffix. - if (Literal.MicrosoftInteger == 128 && MaxWidth < 128 && - Context.getTargetInfo().hasInt128Type()) - MaxWidth = 128; llvm::APInt ResultVal(MaxWidth, 0); if (Literal.GetIntegerValue(ResultVal)) { @@ -3384,12 +3350,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // Microsoft specific integer suffixes are explicitly sized. if (Literal.MicrosoftInteger) { - if (Literal.MicrosoftInteger > MaxWidth) { - // If this target doesn't support __int128, error and force to ull. - Diag(Tok.getLocation(), diag::err_int128_unsupported); - Width = MaxWidth; - Ty = Context.getIntMaxType(); - } else if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) { + if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) { Width = 8; Ty = Context.CharTy; } else { @@ -3726,7 +3687,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) { return false; if (E->getObjectKind() == OK_BitField) { - S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) + S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 1 << E->getSourceRange(); return true; } @@ -3828,7 +3789,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr); isInvalid = true; } else if (E->refersToBitField()) { // C99 6.5.3.4p1. - Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0; + Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 0; isInvalid = true; } else { isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf); @@ -3854,7 +3815,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, ExprResult Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, bool IsType, - void *TyOrEx, const SourceRange &ArgRange) { + void *TyOrEx, SourceRange ArgRange) { // If error parsing type, ignore. if (!TyOrEx) return ExprError(); @@ -3940,9 +3901,21 @@ static bool checkArithmeticOnObjCPointer(Sema &S, return true; } +static bool isMSPropertySubscriptExpr(Sema &S, Expr *Base) { + auto *BaseNoParens = Base->IgnoreParens(); + if (auto *MSProp = dyn_cast<MSPropertyRefExpr>(BaseNoParens)) + return MSProp->getPropertyDecl()->getType()->isArrayType(); + return isa<MSPropertySubscriptExpr>(BaseNoParens); +} + ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, Expr *idx, SourceLocation rbLoc) { + if (base && !base->getType().isNull() && + base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection)) + return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(), + /*Length=*/nullptr, rbLoc); + // Since this might be a postfix expression, get rid of ParenListExprs. if (isa<ParenListExpr>(base)) { ExprResult result = MaybeConvertParenListExprToParenExpr(S, base); @@ -3955,10 +3928,15 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, // operand might be an overloadable type, in which case the overload // resolution for the operator overload should get the first crack // at the overload. + bool IsMSPropertySubscript = false; if (base->getType()->isNonOverloadPlaceholderType()) { - ExprResult result = CheckPlaceholderExpr(base); - if (result.isInvalid()) return ExprError(); - base = result.get(); + IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base); + if (!IsMSPropertySubscript) { + ExprResult result = CheckPlaceholderExpr(base); + if (result.isInvalid()) + return ExprError(); + base = result.get(); + } } if (idx->getType()->isNonOverloadPlaceholderType()) { ExprResult result = CheckPlaceholderExpr(idx); @@ -3973,6 +3951,21 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, VK_LValue, OK_Ordinary, rbLoc); } + // MSDN, property (C++) + // https://msdn.microsoft.com/en-us/library/yhfk0thd(v=vs.120).aspx + // This attribute can also be used in the declaration of an empty array in a + // class or structure definition. For example: + // __declspec(property(get=GetX, put=PutX)) int x[]; + // The above statement indicates that x[] can be used with one or more array + // indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), + // and p->x[a][b] = i will be turned into p->PutX(a, b, i); + if (IsMSPropertySubscript) { + // Build MS property subscript expression if base is MS property reference + // or MS property subscript. + return new (Context) MSPropertySubscriptExpr( + base, idx, Context.PseudoObjectTy, VK_LValue, OK_Ordinary, rbLoc); + } + // Use C++ overloaded-operator rules if either operand has record // type. The spec says to do this if either type is *overloadable*, // but enum types can't declare subscript operators or conversion @@ -3991,6 +3984,139 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc); } +ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, + Expr *LowerBound, + SourceLocation ColonLoc, Expr *Length, + SourceLocation RBLoc) { + if (Base->getType()->isPlaceholderType() && + !Base->getType()->isSpecificPlaceholderType( + BuiltinType::OMPArraySection)) { + ExprResult Result = CheckPlaceholderExpr(Base); + if (Result.isInvalid()) + return ExprError(); + Base = Result.get(); + } + if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) { + ExprResult Result = CheckPlaceholderExpr(LowerBound); + if (Result.isInvalid()) + return ExprError(); + LowerBound = Result.get(); + } + if (Length && Length->getType()->isNonOverloadPlaceholderType()) { + ExprResult Result = CheckPlaceholderExpr(Length); + if (Result.isInvalid()) + return ExprError(); + Length = Result.get(); + } + + // Build an unanalyzed expression if either operand is type-dependent. + if (Base->isTypeDependent() || + (LowerBound && + (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) || + (Length && (Length->isTypeDependent() || Length->isValueDependent()))) { + return new (Context) + OMPArraySectionExpr(Base, LowerBound, Length, Context.DependentTy, + VK_LValue, OK_Ordinary, ColonLoc, RBLoc); + } + + // Perform default conversions. + QualType OriginalTy = OMPArraySectionExpr::getBaseOriginalType(Base); + QualType ResultTy; + if (OriginalTy->isAnyPointerType()) { + ResultTy = OriginalTy->getPointeeType(); + } else if (OriginalTy->isArrayType()) { + ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType(); + } else { + return ExprError( + Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value) + << Base->getSourceRange()); + } + // C99 6.5.2.1p1 + if (LowerBound) { + auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(), + LowerBound); + if (Res.isInvalid()) + return ExprError(Diag(LowerBound->getExprLoc(), + diag::err_omp_typecheck_section_not_integer) + << 0 << LowerBound->getSourceRange()); + LowerBound = Res.get(); + + if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || + LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) + Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char) + << 0 << LowerBound->getSourceRange(); + } + if (Length) { + auto Res = + PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length); + if (Res.isInvalid()) + return ExprError(Diag(Length->getExprLoc(), + diag::err_omp_typecheck_section_not_integer) + << 1 << Length->getSourceRange()); + Length = Res.get(); + + if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || + Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) + Diag(Length->getExprLoc(), diag::warn_omp_section_is_char) + << 1 << Length->getSourceRange(); + } + + // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, + // C++ [expr.sub]p1: The type "T" shall be a completely-defined object + // type. Note that functions are not objects, and that (in C99 parlance) + // incomplete types are not object types. + if (ResultTy->isFunctionType()) { + Diag(Base->getExprLoc(), diag::err_omp_section_function_type) + << ResultTy << Base->getSourceRange(); + return ExprError(); + } + + if (RequireCompleteType(Base->getExprLoc(), ResultTy, + diag::err_omp_section_incomplete_type, Base)) + return ExprError(); + + if (LowerBound) { + llvm::APSInt LowerBoundValue; + if (LowerBound->EvaluateAsInt(LowerBoundValue, Context)) { + // OpenMP 4.0, [2.4 Array Sections] + // The lower-bound and length must evaluate to non-negative integers. + if (LowerBoundValue.isNegative()) { + Diag(LowerBound->getExprLoc(), diag::err_omp_section_negative) + << 0 << LowerBoundValue.toString(/*Radix=*/10, /*Signed=*/true) + << LowerBound->getSourceRange(); + return ExprError(); + } + } + } + + if (Length) { + llvm::APSInt LengthValue; + if (Length->EvaluateAsInt(LengthValue, Context)) { + // OpenMP 4.0, [2.4 Array Sections] + // The lower-bound and length must evaluate to non-negative integers. + if (LengthValue.isNegative()) { + Diag(Length->getExprLoc(), diag::err_omp_section_negative) + << 1 << LengthValue.toString(/*Radix=*/10, /*Signed=*/true) + << Length->getSourceRange(); + return ExprError(); + } + } + } else if (ColonLoc.isValid() && + (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() && + !OriginalTy->isVariableArrayType()))) { + // OpenMP 4.0, [2.4 Array Sections] + // When the size of the array dimension is not known, the length must be + // specified explicitly. + Diag(ColonLoc, diag::err_omp_section_length_undefined) + << (!OriginalTy.isNull() && OriginalTy->isArrayType()); + return ExprError(); + } + + return new (Context) + OMPArraySectionExpr(Base, LowerBound, Length, Context.OMPArraySectionTy, + VK_LValue, OK_Ordinary, ColonLoc, RBLoc); +} + ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc) { @@ -4275,29 +4401,27 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn, llvm::make_unique<FunctionCallCCC>(S, FuncName.getAsIdentifierInfo(), Args.size(), ME), Sema::CTK_ErrorRecovery)) { - if (NamedDecl *ND = Corrected.getCorrectionDecl()) { + if (NamedDecl *ND = Corrected.getFoundDecl()) { if (Corrected.isOverloaded()) { OverloadCandidateSet OCS(NameLoc, OverloadCandidateSet::CSK_Normal); OverloadCandidateSet::iterator Best; - for (TypoCorrection::decl_iterator CD = Corrected.begin(), - CDEnd = Corrected.end(); - CD != CDEnd; ++CD) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD)) + for (NamedDecl *CD : Corrected) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args, OCS); } switch (OCS.BestViableFunction(S, NameLoc, Best)) { case OR_Success: - ND = Best->Function; + ND = Best->FoundDecl; Corrected.setCorrectionDecl(ND); break; default: break; } } - if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { + ND = ND->getUnderlyingDecl(); + if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) return Corrected; - } } } return TypoCorrection(); @@ -4433,7 +4557,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, bool IsListInitialization) { unsigned NumParams = Proto->getNumParams(); bool Invalid = false; - unsigned ArgIx = 0; + size_t ArgIx = 0; // Continue to check argument types (even if we have too few/many args). for (unsigned i = FirstParam; i < NumParams; i++) { QualType ProtoArgType = Proto->getParamType(i); @@ -4503,26 +4627,25 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, // return __unknown_anytype aren't *really* variadic. if (Proto->getReturnType() == Context.UnknownAnyTy && FDecl && FDecl->isExternC()) { - for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) { + for (Expr *A : Args.slice(ArgIx)) { QualType paramType; // ignored - ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType); + ExprResult arg = checkUnknownAnyArg(CallLoc, A, paramType); Invalid |= arg.isInvalid(); AllArgs.push_back(arg.get()); } // Otherwise do argument promotion, (C99 6.5.2.2p7). } else { - for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) { - ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, - FDecl); + for (Expr *A : Args.slice(ArgIx)) { + ExprResult Arg = DefaultVariadicArgumentPromotion(A, CallType, FDecl); Invalid |= Arg.isInvalid(); AllArgs.push_back(Arg.get()); } } // Check for array bounds violations. - for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) - CheckArrayAccess(Args[i]); + for (Expr *A : Args.slice(ArgIx)) + CheckArrayAccess(A); } return Invalid; } @@ -4623,7 +4746,9 @@ static bool isPlaceholderToRemoveAsArg(QualType type) { // These are always invalid as call arguments and should be reported. case BuiltinType::BoundMember: case BuiltinType::BuiltinFn: + case BuiltinType::OMPArraySection: return true; + } llvm_unreachable("bad builtin type kind"); } @@ -4647,7 +4772,7 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) { } /// 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, then 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. @@ -4745,7 +4870,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, // Pseudo-destructor calls should not have any arguments. Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args) << FixItHint::CreateRemoval( - SourceRange(ArgExprs[0]->getLocStart(), + SourceRange(ArgExprs.front()->getLocStart(), ArgExprs.back()->getLocEnd())); } @@ -4802,14 +4927,10 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, // We aren't supposed to apply this logic for if there's an '&' involved. if (!find.HasFormOfMemberPointer) { OverloadExpr *ovl = find.Expression; - if (isa<UnresolvedLookupExpr>(ovl)) { - UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl); + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl)) return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs, RParenLoc, ExecConfig); - } else { - return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, - RParenLoc); - } + return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc); } } @@ -4832,7 +4953,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl); if (FDecl && FDecl->getBuiltinID()) { - // Rewrite the function decl for this builtin by replacing paramaters + // Rewrite the function decl for this builtin by replacing parameters // with no explicit address space with the address space of the arguments // in ArgExprs. if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) { @@ -4949,7 +5070,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (!Result.isUsable()) return ExprError(); TheCall = dyn_cast<CallExpr>(Result.get()); if (!TheCall) return Result; - Args = ArrayRef<Expr *>(TheCall->getArgs(), TheCall->getNumArgs()); + Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()); } // Bail out early if calling a builtin with custom typechecking. @@ -5098,8 +5219,7 @@ ExprResult Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty, SourceLocation RParenLoc, Expr *InitExpr) { assert(Ty && "ActOnCompoundLiteral(): missing type"); - // FIXME: put back this assert when initializers are worked out. - //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression"); + assert(InitExpr && "ActOnCompoundLiteral(): missing expression"); TypeSourceInfo *TInfo; QualType literalType = GetTypeFromParser(Ty, &TInfo); @@ -5280,13 +5400,13 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { return CK_IntegralToFloating; case Type::STK_IntegralComplex: Src = ImpCastExprToType(Src.get(), - DestTy->castAs<ComplexType>()->getElementType(), - CK_IntegralCast); + DestTy->castAs<ComplexType>()->getElementType(), + CK_IntegralCast); return CK_IntegralRealToComplex; case Type::STK_FloatingComplex: Src = ImpCastExprToType(Src.get(), - DestTy->castAs<ComplexType>()->getElementType(), - CK_IntegralToFloating); + DestTy->castAs<ComplexType>()->getElementType(), + CK_IntegralToFloating); return CK_FloatingRealToComplex; case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); @@ -5401,36 +5521,54 @@ static bool breakDownVectorType(QualType type, uint64_t &len, return true; } -static bool VectorTypesMatch(Sema &S, QualType srcTy, QualType destTy) { +/// Are the two types lax-compatible vector types? That is, given +/// that one of them is a vector, do they have equal storage sizes, +/// where the storage size is the number of elements times the element +/// size? +/// +/// This will also return false if either of the types is neither a +/// vector nor a real type. +bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { + assert(destTy->isVectorType() || srcTy->isVectorType()); + + // Disallow lax conversions between scalars and ExtVectors (these + // conversions are allowed for other vector types because common headers + // depend on them). Most scalar OP ExtVector cases are handled by the + // splat path anyway, which does what we want (convert, not bitcast). + // What this rules out for ExtVectors is crazy things like char4*float. + if (srcTy->isScalarType() && destTy->isExtVectorType()) return false; + if (destTy->isScalarType() && srcTy->isExtVectorType()) return false; + uint64_t srcLen, destLen; - QualType srcElt, destElt; - if (!breakDownVectorType(srcTy, srcLen, srcElt)) return false; - if (!breakDownVectorType(destTy, destLen, destElt)) return false; + QualType srcEltTy, destEltTy; + if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false; + if (!breakDownVectorType(destTy, destLen, destEltTy)) return false; // ASTContext::getTypeSize will return the size rounded up to a // power of 2, so instead of using that, we need to use the raw // element size multiplied by the element count. - uint64_t srcEltSize = S.Context.getTypeSize(srcElt); - uint64_t destEltSize = S.Context.getTypeSize(destElt); + uint64_t srcEltSize = Context.getTypeSize(srcEltTy); + uint64_t destEltSize = Context.getTypeSize(destEltTy); return (srcLen * srcEltSize == destLen * destEltSize); } -/// Is this a legal conversion between two known vector types? +/// Is this a legal conversion between two types, one of which is +/// known to be a vector type? bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) { assert(destTy->isVectorType() || srcTy->isVectorType()); if (!Context.getLangOpts().LaxVectorConversions) return false; - return VectorTypesMatch(*this, srcTy, destTy); + return areLaxCompatibleVectorTypes(srcTy, destTy); } bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, CastKind &Kind) { assert(VectorTy->isVectorType() && "Not a vector type!"); - if (Ty->isVectorType() || Ty->isIntegerType()) { - if (!VectorTypesMatch(*this, Ty, VectorTy)) + if (Ty->isVectorType() || Ty->isIntegralType(Context)) { + if (!areLaxCompatibleVectorTypes(Ty, VectorTy)) return Diag(R.getBegin(), Ty->isVectorType() ? diag::err_invalid_conversion_between_vectors : @@ -5456,7 +5594,7 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, // In OpenCL, casts between vectors of different types are not allowed. // (See OpenCL 6.2). if (SrcTy->isVectorType()) { - if (!VectorTypesMatch(*this, SrcTy, DestTy) + if (!areLaxCompatibleVectorTypes(SrcTy, DestTy) || (getLangOpts().OpenCL && (DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) { Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) @@ -6358,7 +6496,7 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, static void SuggestParentheses(Sema &Self, SourceLocation Loc, const PartialDiagnostic &Note, SourceRange ParenRange) { - SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd()); + SourceLocation EndLoc = Self.getLocForEndOfToken(ParenRange.getEnd()); if (ParenRange.getBegin().isFileID() && ParenRange.getEnd().isFileID() && EndLoc.isValid()) { Self.Diag(Loc, Note) @@ -6371,7 +6509,9 @@ static void SuggestParentheses(Sema &Self, SourceLocation Loc, } static bool IsArithmeticOp(BinaryOperatorKind Opc) { - return Opc >= BO_Mul && Opc <= BO_Shr; + return BinaryOperator::isAdditiveOp(Opc) || + BinaryOperator::isMultiplicativeOp(Opc) || + BinaryOperator::isShiftOp(Opc); } /// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary @@ -6417,10 +6557,6 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, return false; } -static bool IsLogicOp(BinaryOperatorKind Opc) { - return (Opc >= BO_LT && Opc <= BO_NE) || (Opc >= BO_LAnd && Opc <= BO_LOr); -} - /// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type /// or is a logical expression such as (x==y) which has int type, but is /// commonly interpreted as boolean. @@ -6430,7 +6566,7 @@ static bool ExprLooksBoolean(Expr *E) { if (E->getType()->isBooleanType()) return true; if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) - return IsLogicOp(OP->getOpcode()); + return OP->isComparisonOp() || OP->isLogicalOp(); if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E)) return OP->getOpcode() == UO_LNot; if (E->getType()->isPointerType()) @@ -6753,7 +6889,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc, ExprResult RHSPtr = &RHSExpr; CastKind K = CK_Invalid; - return CheckAssignmentConstraints(LHSType, RHSPtr, K); + return CheckAssignmentConstraints(LHSType, RHSPtr, K, /*ConvertRHS=*/false); } /// CheckAssignmentConstraints (C99 6.5.16) - This routine currently @@ -6775,7 +6911,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc, /// Sets 'Kind' for any result kind except Incompatible. Sema::AssignConvertType Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, - CastKind &Kind) { + CastKind &Kind, bool ConvertRHS) { QualType RHSType = RHS.get()->getType(); QualType OrigLHSType = LHSType; @@ -6797,7 +6933,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind); if (result != Compatible) return result; - if (Kind != CK_NoOp) + if (Kind != CK_NoOp && ConvertRHS) RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind); Kind = CK_NonAtomicToAtomic; return Compatible; @@ -6827,7 +6963,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // CK_VectorSplat does T -> vector T, so first cast to the // element type. QualType elType = cast<ExtVectorType>(LHSType)->getElementType(); - if (elType != RHSType) { + if (elType != RHSType && ConvertRHS) { Kind = PrepareScalarCast(RHS, elType); RHS = ImpCastExprToType(RHS.get(), elType, Kind); } @@ -6860,7 +6996,8 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // Arithmetic conversions. if (LHSType->isArithmeticType() && RHSType->isArithmeticType() && !(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) { - Kind = PrepareScalarCast(RHS, LHSType); + if (ConvertRHS) + Kind = PrepareScalarCast(RHS, LHSType); return Compatible; } @@ -6985,7 +7122,8 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // Only under strict condition T^ is compatible with an Objective-C pointer. if (RHSType->isBlockPointerType() && LHSType->isBlockCompatibleObjCPointerType(Context)) { - maybeExtendBlockObject(RHS); + if (ConvertRHS) + maybeExtendBlockObject(RHS); Kind = CK_BlockPointerToObjCPointerCast; return Compatible; } @@ -7111,9 +7249,16 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, } Sema::AssignConvertType -Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, +Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, bool Diagnose, - bool DiagnoseCFAudited) { + bool DiagnoseCFAudited, + bool ConvertRHS) { + // If ConvertRHS is false, we want to leave the caller's RHS untouched. Sadly, + // we can't avoid *all* modifications at the moment, so we need some somewhere + // to put the updated value. + ExprResult LocalRHS = CallerRHS; + ExprResult &RHS = ConvertRHS ? CallerRHS : LocalRHS; + if (getLangOpts().CPlusPlus) { if (!LHSType->isRecordType() && !LHSType->isAtomicType()) { // C++ 5.17p3: If the left operand is not of class type, the @@ -7151,6 +7296,15 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, // structures. // FIXME: We also fall through for atomics; not sure what should // happen there, though. + } else if (RHS.get()->getType() == Context.OverloadTy) { + // As a set of extensions to C, we support overloading on functions. These + // functions need to be resolved here. + DeclAccessPair DAP; + if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction( + RHS.get(), LHSType, /*Complain=*/false, DAP)) + RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD); + else + return Incompatible; } // C99 6.5.16.1p1: the left operand is a pointer and the right is @@ -7162,7 +7316,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, CastKind Kind; CXXCastPath Path; CheckPointerConversion(RHS.get(), LHSType, Kind, Path, false); - RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path); + if (ConvertRHS) + RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path); return Compatible; } @@ -7173,7 +7328,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, // // Suppress this for references: C++ 8.5.3p5. if (!LHSType->isReferenceType()) { - RHS = DefaultFunctionArrayLvalueConversion(RHS.get()); + // FIXME: We potentially allocate here even if ConvertRHS is false. + RHS = DefaultFunctionArrayLvalueConversion(RHS.get(), Diagnose); if (RHS.isInvalid()) return Incompatible; } @@ -7189,7 +7345,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, CastKind Kind = CK_Invalid; Sema::AssignConvertType result = - CheckAssignmentConstraints(LHSType, RHS, Kind); + CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS); // C99 6.5.16.1p2: The value of the right operand is converted to the // type of the assignment expression. @@ -7211,7 +7367,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, return Compatible; } - RHS = ImpCastExprToType(E, Ty, Kind); + if (ConvertRHS) + RHS = ImpCastExprToType(E, Ty, Kind); } return result; } @@ -7374,6 +7531,18 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); } + // OpenCL V1.1 6.2.6.p1: + // If the operands are of more than one vector type, then an error shall + // occur. Implicit conversions between vector types are not permitted, per + // section 6.2.1. + if (getLangOpts().OpenCL && + RHSVecType && isa<ExtVectorType>(RHSVecType) && + LHSVecType && isa<ExtVectorType>(LHSVecType)) { + Diag(Loc, diag::err_opencl_implicit_vector_conversion) << LHSType + << RHSType; + return QualType(); + } + // Otherwise, use the generic diagnostic. Diag(Loc, diag::err_typecheck_vector_not_convertable) << LHSType << RHSType @@ -7420,6 +7589,18 @@ static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS, << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); } +static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS, + ExprResult &RHS, + SourceLocation Loc, bool IsDiv) { + // Check for division/remainder by zero. + llvm::APSInt RHSValue; + if (!RHS.get()->isValueDependent() && + RHS.get()->EvaluateAsInt(RHSValue, S.Context) && RHSValue == 0) + S.DiagRuntimeBehavior(Loc, RHS.get(), + S.PDiag(diag::warn_remainder_division_by_zero) + << IsDiv << RHS.get()->getSourceRange()); +} + QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign, bool IsDiv) { @@ -7438,15 +7619,8 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, if (compType.isNull() || !compType->isArithmeticType()) return InvalidOperands(Loc, LHS, RHS); - - // Check for division by zero. - llvm::APSInt RHSValue; - if (IsDiv && !RHS.get()->isValueDependent() && - RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0) - DiagRuntimeBehavior(Loc, RHS.get(), - PDiag(diag::warn_division_by_zero) - << RHS.get()->getSourceRange()); - + if (IsDiv) + DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv); return compType; } @@ -7470,15 +7644,7 @@ QualType Sema::CheckRemainderOperands( if (compType.isNull() || !compType->isIntegerType()) return InvalidOperands(Loc, LHS, RHS); - - // Check for remainder by zero. - llvm::APSInt RHSValue; - if (!RHS.get()->isValueDependent() && - RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0) - DiagRuntimeBehavior(Loc, RHS.get(), - PDiag(diag::warn_remainder_by_zero) - << RHS.get()->getSourceRange()); - + DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */); return compType; } @@ -7596,7 +7762,7 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc, if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType(); // if both are pointers check if operation is valid wrt address spaces - if (isLHSPointer && isRHSPointer) { + if (S.getLangOpts().OpenCL && isLHSPointer && isRHSPointer) { const PointerType *lhsPtr = LHSExpr->getType()->getAs<PointerType>(); const PointerType *rhsPtr = RHSExpr->getType()->getAs<PointerType>(); if (!lhsPtr->isAddressSpaceOverlapping(*rhsPtr)) { @@ -7669,7 +7835,7 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc, // Only print a fixit for "str" + int, not for int + "str". if (IndexExpr == RHSExpr) { - SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd()); + SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd()); Self.Diag(OpLoc, diag::note_string_plus_scalar_silence) << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&") << FixItHint::CreateReplacement(SourceRange(OpLoc), "[") @@ -7719,7 +7885,7 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc, // Only print a fixit for str + char, not for char + str. if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) { - SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd()); + SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd()); Self.Diag(OpLoc, diag::note_string_plus_scalar_silence) << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&") << FixItHint::CreateReplacement(SourceRange(OpLoc), "[") @@ -7739,9 +7905,10 @@ static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc, << RHSExpr->getSourceRange(); } -QualType Sema::CheckAdditionOperands( // C99 6.5.6 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, - QualType* CompLHSTy) { +// C99 6.5.6 +QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, BinaryOperatorKind Opc, + QualType* CompLHSTy) { checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); if (LHS.get()->getType()->isVectorType() || @@ -7917,7 +8084,7 @@ static bool isScopedEnumerationType(QualType T) { } static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, unsigned Opc, + SourceLocation Loc, BinaryOperatorKind Opc, QualType LHSType) { // OpenCL 6.3j: shift values are effectively % word size of LHS (more defined), // so skip remaining warnings as we don't want to modify values within Sema. @@ -8060,7 +8227,7 @@ static QualType checkOpenCLVectorShift(Sema &S, // C99 6.5.7 QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, unsigned Opc, + SourceLocation Loc, BinaryOperatorKind Opc, bool IsCompAssign) { checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); @@ -8365,9 +8532,9 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, if (BinaryOperator::isEqualityOp(Opc) && hasIsEqualMethod(S, LHS.get(), RHS.get())) { SourceLocation Start = LHS.get()->getLocStart(); - SourceLocation End = S.PP.getLocForEndOfToken(RHS.get()->getLocEnd()); + SourceLocation End = S.getLocForEndOfToken(RHS.get()->getLocEnd()); CharSourceRange OpRange = - CharSourceRange::getCharRange(Loc, S.PP.getLocForEndOfToken(Loc)); + CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc)); S.Diag(Loc, diag::note_objc_literal_comparison_isequal) << FixItHint::CreateInsertion(Start, Opc == BO_EQ ? "[" : "![") @@ -8379,20 +8546,17 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - unsigned OpaqueOpc) { - // This checking requires bools. - if (!S.getLangOpts().Bool) return; - + BinaryOperatorKind Opc) { // Check that left hand side is !something. UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS.get()->IgnoreImpCasts()); if (!UO || UO->getOpcode() != UO_LNot) return; // Only check if the right hand side is non-bool arithmetic type. - if (RHS.get()->getType()->isBooleanType()) return; + if (RHS.get()->isKnownToHaveBooleanValue()) return; // Make sure that the something in !something is not bool. Expr *SubExpr = UO->getSubExpr()->IgnoreImpCasts(); - if (SubExpr->getType()->isBooleanType()) return; + if (SubExpr->isKnownToHaveBooleanValue()) return; // Emit warning. S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_comparison) @@ -8401,7 +8565,7 @@ static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS, // First note suggest !(x < y) SourceLocation FirstOpen = SubExpr->getLocStart(); SourceLocation FirstClose = RHS.get()->getLocEnd(); - FirstClose = S.getPreprocessor().getLocForEndOfToken(FirstClose); + FirstClose = S.getLocForEndOfToken(FirstClose); if (FirstClose.isInvalid()) FirstOpen = SourceLocation(); S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix) @@ -8411,7 +8575,7 @@ static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS, // Second note suggests (!x) < y SourceLocation SecondOpen = LHS.get()->getLocStart(); SourceLocation SecondClose = LHS.get()->getLocEnd(); - SecondClose = S.getPreprocessor().getLocForEndOfToken(SecondClose); + SecondClose = S.getLocForEndOfToken(SecondClose); if (SecondClose.isInvalid()) SecondOpen = SourceLocation(); S.Diag(UO->getOperatorLoc(), diag::note_logical_not_silence_with_parens) @@ -8437,12 +8601,10 @@ static ValueDecl *getCompareDecl(Expr *E) { // C99 6.5.8, C++ [expr.rel] QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, unsigned OpaqueOpc, + SourceLocation Loc, BinaryOperatorKind Opc, bool IsRelational) { checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true); - BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc; - // Handle vector comparisons separately. if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) @@ -8455,7 +8617,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts(); checkEnumComparison(*this, Loc, LHS.get(), RHS.get()); - diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, OpaqueOpc); + diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, Opc); if (!LHSType->hasFloatingRepresentation() && !(LHSType->isBlockPointerType() && IsRelational) && @@ -8628,12 +8790,15 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false); } if (LCanPointeeTy != RCanPointeeTy) { - const PointerType *lhsPtr = LHSType->getAs<PointerType>(); - if (!lhsPtr->isAddressSpaceOverlapping(*RHSType->getAs<PointerType>())) { - Diag(Loc, - diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) - << LHSType << RHSType << 0 /* comparison */ - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + // Treat NULL constant as a special case in OpenCL. + if (getLangOpts().OpenCL && !LHSIsNull && !RHSIsNull) { + const PointerType *LHSPtr = LHSType->getAs<PointerType>(); + if (!LHSPtr->isAddressSpaceOverlapping(*RHSType->getAs<PointerType>())) { + Diag(Loc, + diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) + << LHSType << RHSType << 0 /* comparison */ + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + } } unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace(); unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace(); @@ -8941,9 +9106,10 @@ inline QualType Sema::CheckBitwiseOperands( return InvalidOperands(Loc, LHS, RHS); } -inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc) { - +// C99 6.5.[13,14] +inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, + BinaryOperatorKind Opc) { // Check vector operands differently. if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) return CheckVectorLogicalOperands(LHS, RHS, Loc); @@ -8972,18 +9138,14 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator) << (Opc == BO_LAnd ? "&" : "|") << FixItHint::CreateReplacement(SourceRange( - Loc, Lexer::getLocForEndOfToken(Loc, 0, getSourceManager(), - getLangOpts())), + Loc, getLocForEndOfToken(Loc)), Opc == BO_LAnd ? "&" : "|"); if (Opc == BO_LAnd) // Suggest replacing "Foo() && kNonZero" with "Foo()" Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant) << FixItHint::CreateRemoval( - SourceRange( - Lexer::getLocForEndOfToken(LHS.get()->getLocEnd(), - 0, getSourceManager(), - getLangOpts()), - RHS.get()->getLocEnd())); + SourceRange(getLocForEndOfToken(LHS.get()->getLocEnd()), + RHS.get()->getLocEnd())); } } @@ -9161,7 +9323,7 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E, if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { // Function calls const FunctionDecl *FD = CE->getDirectCallee(); - if (!IsTypeModifiable(FD->getReturnType(), IsDereference)) { + if (FD && !IsTypeModifiable(FD->getReturnType(), IsDereference)) { if (!DiagnosticEmitted) { S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstFunction << FD; @@ -9510,7 +9672,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, return QualType(); } // Increment of bool sets it to true, but is deprecated. - S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange(); + S.Diag(OpLoc, S.getLangOpts().CPlusPlus1z ? diag::ext_increment_bool + : diag::warn_increment_bool) + << Op->getSourceRange(); } else if (S.getLangOpts().CPlusPlus && ResType->isEnumeralType()) { // Error on enum increments and decrements in C++ mode S.Diag(OpLoc, diag::err_increment_decrement_enum) << IsInc << ResType; @@ -9710,6 +9874,12 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { // expressions here, but the result of one is always an lvalue anyway. } ValueDecl *dcl = getPrimaryDecl(op); + + if (auto *FD = dyn_cast_or_null<FunctionDecl>(dcl)) + if (!checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, + op->getLocStart())) + return QualType(); + Expr::LValueClassification lval = op->ClassifyLValue(Context); unsigned AddressOfError = AO_No_Error; @@ -9763,8 +9933,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { QualType MPTy = Context.getMemberPointerType( op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); + // Under the MS ABI, lock down the inheritance model now. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) - RequireCompleteType(OpLoc, MPTy, 0); + (void)isCompleteType(OpLoc, MPTy); return MPTy; } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) { // C99 6.5.3.2p1 @@ -9819,8 +9990,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { QualType MPTy = Context.getMemberPointerType( op->getType(), Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr()); + // Under the MS ABI, lock down the inheritance model now. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) - RequireCompleteType(OpLoc, MPTy, 0); + (void)isCompleteType(OpLoc, MPTy); return MPTy; } } @@ -10121,6 +10293,20 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, return ExprError(); } + if (getLangOpts().OpenCL) { + // OpenCLC v2.0 s6.13.11.1 allows atomic variables to be initialized by + // the ATOMIC_VAR_INIT macro. + if (LHSExpr->getType()->isAtomicType() || + RHSExpr->getType()->isAtomicType()) { + SourceRange SR(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); + if (BO_Assign == Opc) + Diag(OpLoc, diag::err_atomic_init_constant) << SR; + else + ResultTy = InvalidOperands(OpLoc, LHS, RHS); + return ExprError(); + } + } + switch (Opc) { case BO_Assign: ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType()); @@ -10211,7 +10397,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BO_AndAssign: case BO_OrAssign: // fallthrough - DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc); + DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc); case BO_XorAssign: CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, true); CompLHSTy = CompResultTy; @@ -10238,7 +10424,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, &Context.Idents.get("object_setClass"), SourceLocation(), LookupOrdinaryName); if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) { - SourceLocation RHSLocEnd = PP.getLocForEndOfToken(RHS.get()->getLocEnd()); + SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getLocEnd()); Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign) << FixItHint::CreateInsertion(LHS.get()->getLocStart(), "object_setClass(") << FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc), ",") << @@ -10274,17 +10460,17 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, BinaryOperator *LHSBO = dyn_cast<BinaryOperator>(LHSExpr); BinaryOperator *RHSBO = dyn_cast<BinaryOperator>(RHSExpr); - // Check that one of the sides is a comparison operator. + // Check that one of the sides is a comparison operator and the other isn't. bool isLeftComp = LHSBO && LHSBO->isComparisonOp(); bool isRightComp = RHSBO && RHSBO->isComparisonOp(); - if (!isLeftComp && !isRightComp) + if (isLeftComp == isRightComp) return; // Bitwise operations are sometimes used as eager logical ops. // Don't diagnose this. bool isLeftBitwise = LHSBO && LHSBO->isBitwiseOp(); bool isRightBitwise = RHSBO && RHSBO->isBitwiseOp(); - if ((isLeftComp || isLeftBitwise) && (isRightComp || isRightBitwise)) + if (isLeftBitwise || isRightBitwise) return; SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(), @@ -10306,21 +10492,6 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, ParensRange); } -/// \brief It accepts a '&' expr that is inside a '|' one. -/// Emit a diagnostic together with a fixit hint that wraps the '&' expression -/// in parentheses. -static void -EmitDiagnosticForBitwiseAndInBitwiseOr(Sema &Self, SourceLocation OpLoc, - BinaryOperator *Bop) { - assert(Bop->getOpcode() == BO_And); - Self.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_and_in_bitwise_or) - << Bop->getSourceRange() << OpLoc; - SuggestParentheses(Self, Bop->getOperatorLoc(), - Self.PDiag(diag::note_precedence_silence) - << Bop->getOpcodeStr(), - Bop->getSourceRange()); -} - /// \brief It accepts a '&&' expr that is inside a '||' one. /// Emit a diagnostic together with a fixit hint that wraps the '&&' expression /// in parentheses. @@ -10389,12 +10560,21 @@ static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc, } } -/// \brief Look for '&' in the left or right hand of a '|' expr. -static void DiagnoseBitwiseAndInBitwiseOr(Sema &S, SourceLocation OpLoc, - Expr *OrArg) { - if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrArg)) { - if (Bop->getOpcode() == BO_And) - return EmitDiagnosticForBitwiseAndInBitwiseOr(S, OpLoc, Bop); +/// \brief Look for bitwise op in the left or right hand of a bitwise op with +/// lower precedence and emit a diagnostic together with a fixit hint that wraps +/// the '&' expression in parentheses. +static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc, + SourceLocation OpLoc, Expr *SubExpr) { + if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(SubExpr)) { + if (Bop->isBitwiseOp() && Bop->getOpcode() < Opc) { + S.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_op_in_bitwise_op) + << Bop->getOpcodeStr() << BinaryOperator::getOpcodeStr(Opc) + << Bop->getSourceRange() << OpLoc; + SuggestParentheses(S, Bop->getOperatorLoc(), + S.PDiag(diag::note_precedence_silence) + << Bop->getOpcodeStr(), + Bop->getSourceRange()); + } } } @@ -10449,9 +10629,10 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, DiagnoseBitwisePrecedence(Self, Opc, OpLoc, LHSExpr, RHSExpr); // Diagnose "arg1 & arg2 | arg3" - if (Opc == BO_Or && !OpLoc.isMacroID()/* Don't warn in macros. */) { - DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, LHSExpr); - DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, RHSExpr); + if ((Opc == BO_Or || Opc == BO_Xor) && + !OpLoc.isMacroID()/* Don't warn in macros. */) { + DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, LHSExpr); + DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, RHSExpr); } // Warn about arg1 || arg2 && arg3, as GCC 4.3+ does. @@ -10593,6 +10774,14 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; QualType resultType; + if (getLangOpts().OpenCL) { + // The only legal unary operation for atomics is '&'. + if (Opc != UO_AddrOf && InputExpr->getType()->isAtomicType()) { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << InputExpr->getType() + << Input.get()->getSourceRange()); + } + } switch (Opc) { case UO_PreInc: case UO_PreDec: @@ -10735,6 +10924,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, } break; case UO_Extension: + case UO_Coawait: resultType = Input.get()->getType(); VK = Input.get()->getValueKind(); OK = Input.get()->getObjectKind(); @@ -10778,10 +10968,8 @@ static bool isQualifiedMemberAccess(Expr *E) { if (!ULE->getQualifier()) return false; - for (UnresolvedLookupExpr::decls_iterator D = ULE->decls_begin(), - DEnd = ULE->decls_end(); - D != DEnd; ++D) { - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*D)) { + for (NamedDecl *D : ULE->decls()) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { if (Method->isInstance()) return true; } else { @@ -10971,8 +11159,7 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, TypeSourceInfo *TInfo, - OffsetOfComponent *CompPtr, - unsigned NumComponents, + ArrayRef<OffsetOfComponent> Components, SourceLocation RParenLoc) { QualType ArgTy = TInfo->getType(); bool Dependent = ArgTy->isDependentType(); @@ -10996,17 +11183,15 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // GCC extension, diagnose them. // FIXME: This diagnostic isn't actually visible because the location is in // a system header! - if (NumComponents != 1) + if (Components.size() != 1) Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator) - << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd); + << SourceRange(Components[1].LocStart, Components.back().LocEnd); bool DidWarnAboutNonPOD = false; QualType CurrentType = ArgTy; - typedef OffsetOfExpr::OffsetOfNode OffsetOfNode; SmallVector<OffsetOfNode, 4> Comps; SmallVector<Expr*, 4> Exprs; - for (unsigned i = 0; i != NumComponents; ++i) { - const OffsetOfComponent &OC = CompPtr[i]; + for (const OffsetOfComponent &OC : Components) { if (OC.isBrackets) { // Offset of an array sub-field. TODO: Should we allow vector elements? if (!CurrentType->isDependentType()) { @@ -11074,7 +11259,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, if (!IsSafe && !DidWarnAboutNonPOD && DiagRuntimeBehavior(BuiltinLoc, nullptr, PDiag(DiagID) - << SourceRange(CompPtr[0].LocStart, OC.LocEnd) + << SourceRange(Components[0].LocStart, OC.LocEnd) << CurrentType)) DidWarnAboutNonPOD = true; } @@ -11113,7 +11298,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // If the member was found in a base class, introduce OffsetOfNodes for // the base class indirections. CXXBasePaths Paths; - if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) { + if (IsDerivedFrom(OC.LocStart, CurrentType, Context.getTypeDeclType(Parent), + Paths)) { if (Paths.getDetectedVirtual()) { Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base) << MemberDecl->getDeclName() @@ -11122,9 +11308,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, } CXXBasePath &Path = Paths.front(); - for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end(); - B != BEnd; ++B) - Comps.push_back(OffsetOfNode(B->Base)); + for (const CXXBasePathElement &B : Path) + Comps.push_back(OffsetOfNode(B.Base)); } if (IndirectMemberDecl) { @@ -11147,8 +11332,7 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc, SourceLocation TypeLoc, ParsedType ParsedArgTy, - OffsetOfComponent *CompPtr, - unsigned NumComponents, + ArrayRef<OffsetOfComponent> Components, SourceLocation RParenLoc) { TypeSourceInfo *ArgTInfo; @@ -11159,8 +11343,7 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, if (!ArgTInfo) ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc); - return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents, - RParenLoc); + return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, Components, RParenLoc); } @@ -11394,16 +11577,14 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // Set the captured variables on the block. // FIXME: Share capture structure between BlockDecl and CapturingScopeInfo! SmallVector<BlockDecl::Capture, 4> Captures; - for (unsigned i = 0, e = BSI->Captures.size(); i != e; i++) { - CapturingScopeInfo::Capture &Cap = BSI->Captures[i]; + for (CapturingScopeInfo::Capture &Cap : BSI->Captures) { if (Cap.isThisCapture()) continue; BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(), Cap.isNested(), Cap.getInitExpr()); Captures.push_back(NewCap); } - BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(), - BSI->CXXThisCaptureIndex != 0); + BSI->TheDecl->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0); // If the user wrote a function type in some form, try to use that. if (!BSI->FunctionType.isNull()) { @@ -11495,43 +11676,57 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E, TypeSourceInfo *TInfo, SourceLocation RPLoc) { Expr *OrigExpr = E; + bool IsMS = false; + + // It might be a __builtin_ms_va_list. (But don't ever mark a va_arg() + // as Microsoft ABI on an actual Microsoft platform, where + // __builtin_ms_va_list and __builtin_va_list are the same.) + if (!E->isTypeDependent() && Context.getTargetInfo().hasBuiltinMSVaList() && + Context.getTargetInfo().getBuiltinVaListKind() != TargetInfo::CharPtrBuiltinVaList) { + QualType MSVaListType = Context.getBuiltinMSVaListType(); + if (Context.hasSameType(MSVaListType, E->getType())) { + if (CheckForModifiableLvalue(E, BuiltinLoc, *this)) + return ExprError(); + IsMS = true; + } + } // Get the va_list type QualType VaListType = Context.getBuiltinVaListType(); - if (VaListType->isArrayType()) { - // Deal with implicit array decay; for example, on x86-64, - // va_list is an array, but it's supposed to decay to - // a pointer for va_arg. - VaListType = Context.getArrayDecayedType(VaListType); - // Make sure the input expression also decays appropriately. - ExprResult Result = UsualUnaryConversions(E); - if (Result.isInvalid()) - return ExprError(); - E = Result.get(); - } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) { - // If va_list is a record type and we are compiling in C++ mode, - // check the argument using reference binding. - InitializedEntity Entity - = InitializedEntity::InitializeParameter(Context, - Context.getLValueReferenceType(VaListType), false); - ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E); - if (Init.isInvalid()) - return ExprError(); - E = Init.getAs<Expr>(); - } else { - // Otherwise, the va_list argument must be an l-value because - // it is modified by va_arg. - if (!E->isTypeDependent() && - CheckForModifiableLvalue(E, BuiltinLoc, *this)) - return ExprError(); + if (!IsMS) { + if (VaListType->isArrayType()) { + // Deal with implicit array decay; for example, on x86-64, + // va_list is an array, but it's supposed to decay to + // a pointer for va_arg. + VaListType = Context.getArrayDecayedType(VaListType); + // Make sure the input expression also decays appropriately. + ExprResult Result = UsualUnaryConversions(E); + if (Result.isInvalid()) + return ExprError(); + E = Result.get(); + } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) { + // If va_list is a record type and we are compiling in C++ mode, + // check the argument using reference binding. + InitializedEntity Entity = InitializedEntity::InitializeParameter( + Context, Context.getLValueReferenceType(VaListType), false); + ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E); + if (Init.isInvalid()) + return ExprError(); + E = Init.getAs<Expr>(); + } else { + // Otherwise, the va_list argument must be an l-value because + // it is modified by va_arg. + if (!E->isTypeDependent() && + CheckForModifiableLvalue(E, BuiltinLoc, *this)) + return ExprError(); + } } - if (!E->isTypeDependent() && - !Context.hasSameType(VaListType, E->getType())) { + if (!IsMS && !E->isTypeDependent() && + !Context.hasSameType(VaListType, E->getType())) return ExprError(Diag(E->getLocStart(), diag::err_first_argument_to_va_arg_not_of_type_va_list) << OrigExpr->getType() << E->getSourceRange()); - } if (!TInfo->getType()->isDependentType()) { if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(), @@ -11573,7 +11768,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, } QualType T = TInfo->getType().getNonLValueExprType(Context); - return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T); + return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T, IsMS); } ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { @@ -11627,6 +11822,25 @@ Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp) { return true; } +static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType, + const Expr *SrcExpr) { + if (!DstType->isFunctionPointerType() || + !SrcExpr->getType()->isFunctionType()) + return false; + + auto *DRE = dyn_cast<DeclRefExpr>(SrcExpr->IgnoreParenImpCasts()); + if (!DRE) + return false; + + auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()); + if (!FD) + return false; + + return !S.checkAddressOfFunctionIsAvailable(FD, + /*Complain=*/true, + SrcExpr->getLocStart()); +} + bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, QualType DstType, QualType SrcType, @@ -11759,6 +11973,12 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, DiagKind = diag::err_arc_weak_unavailable_assign; break; case Incompatible: + if (maybeDiagnoseAssignmentToFunction(*this, DstType, SrcExpr)) { + if (Complained) + *Complained = true; + return true; + } + DiagKind = diag::err_typecheck_convert_incompatible; ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); MayHaveConvFixit = true; @@ -11797,9 +12017,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, // If we can fix the conversion, suggest the FixIts. assert(ConvHints.isNull() || Hint.isNull()); if (!ConvHints.isNull()) { - for (std::vector<FixItHint>::iterator HI = ConvHints.Hints.begin(), - HE = ConvHints.Hints.end(); HI != HE; ++HI) - FDiag << *HI; + for (FixItHint &H : ConvHints.Hints) + FDiag << H; } else { FDiag << Hint; } @@ -11816,7 +12035,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, if (SecondType == Context.OverloadTy) NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression, - FirstType); + FirstType, /*TakingAddress=*/true); if (CheckInferredResultType) EmitRelatedResultTypeNote(SrcExpr); @@ -11974,16 +12193,16 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, if (!Folded || !AllowFold) { if (!Diagnoser.Suppress) { Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange()); - for (unsigned I = 0, N = Notes.size(); I != N; ++I) - Diag(Notes[I].first, Notes[I].second); + for (const PartialDiagnosticAt &Note : Notes) + Diag(Note.first, Note.second); } return ExprError(); } Diagnoser.diagnoseFold(*this, DiagLoc, E->getSourceRange()); - for (unsigned I = 0, N = Notes.size(); I != N; ++I) - Diag(Notes[I].first, Notes[I].second); + for (const PartialDiagnosticAt &Note : Notes) + Diag(Note.first, Note.second); if (Result) *Result = EvalResult.Val.getInt(); @@ -12417,10 +12636,15 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDec // Compute the type of an expression that refers to this variable. DeclRefType = CaptureType.getNonReferenceType(); - + + // Similarly to mutable captures in lambda, all the OpenMP captures by copy + // are mutable in the sense that user can change their value - they are + // private instances of the captured declarations. const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var); if (Cap.isCopyCapture() && - !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable)) + !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable) && + !(isa<CapturedRegionScopeInfo>(CSI) && + cast<CapturedRegionScopeInfo>(CSI)->CapRegionKind == CR_OpenMP)) DeclRefType.addConst(); return true; } @@ -12608,9 +12832,17 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, // By default, capture variables by reference. bool ByRef = true; // Using an LValue reference type is consistent with Lambdas (see below). - if (S.getLangOpts().OpenMP && S.IsOpenMPCapturedVar(Var)) - DeclRefType = DeclRefType.getUnqualifiedType(); - CaptureType = S.Context.getLValueReferenceType(DeclRefType); + if (S.getLangOpts().OpenMP) { + ByRef = S.IsOpenMPCapturedByRef(Var, RSI); + if (S.IsOpenMPCapturedVar(Var)) + DeclRefType = DeclRefType.getUnqualifiedType(); + } + + if (ByRef) + CaptureType = S.Context.getLValueReferenceType(DeclRefType); + else + CaptureType = DeclRefType; + Expr *CopyExpr = nullptr; if (BuildAndDiagnose) { // The current implementation assumes that all variables are captured @@ -12836,21 +13068,6 @@ bool Sema::tryCaptureVariable( if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType, DeclRefType)) break; - if (getLangOpts().OpenMP) { - if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { - // OpenMP private variables should not be captured in outer scope, so - // just break here. - if (RSI->CapRegionKind == CR_OpenMP) { - if (isOpenMPPrivateVar(Var, OpenMPLevel)) { - Nested = true; - DeclRefType = DeclRefType.getUnqualifiedType(); - CaptureType = Context.getLValueReferenceType(DeclRefType); - break; - } - ++OpenMPLevel; - } - } - } // If we are instantiating a generic lambda call operator body, // we do not want to capture new variables. What was captured // during either a lambdas transformation or initial parsing @@ -12996,6 +13213,29 @@ bool Sema::tryCaptureVariable( } while (!QTy.isNull() && QTy->isVariablyModifiedType()); } + if (getLangOpts().OpenMP) { + if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { + // OpenMP private variables should not be captured in outer scope, so + // just break here. Similarly, global variables that are captured in a + // target region should not be captured outside the scope of the region. + if (RSI->CapRegionKind == CR_OpenMP) { + auto isTargetCap = isOpenMPTargetCapturedVar(Var, OpenMPLevel); + // When we detect target captures we are looking from inside the + // target region, therefore we need to propagate the capture from the + // enclosing region. Therefore, the capture is not initially nested. + if (isTargetCap) + FunctionScopesIndex--; + + if (isTargetCap || isOpenMPPrivateVar(Var, OpenMPLevel)) { + Nested = !isTargetCap; + DeclRefType = DeclRefType.getUnqualifiedType(); + CaptureType = Context.getLValueReferenceType(DeclRefType); + break; + } + ++OpenMPLevel; + } + } + } if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) { // No capture-default, and this is not an explicit capture // so cannot capture this variable. @@ -13152,15 +13392,13 @@ ExprResult Sema::ActOnConstantExpression(ExprResult Res) { } void Sema::CleanupVarDeclMarking() { - for (llvm::SmallPtrSetIterator<Expr*> i = MaybeODRUseExprs.begin(), - e = MaybeODRUseExprs.end(); - i != e; ++i) { + for (Expr *E : MaybeODRUseExprs) { VarDecl *Var; SourceLocation Loc; - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*i)) { + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { Var = cast<VarDecl>(DRE->getDecl()); Loc = DRE->getLocation(); - } else if (MemberExpr *ME = dyn_cast<MemberExpr>(*i)) { + } else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { Var = cast<VarDecl>(ME->getMemberDecl()); Loc = ME->getMemberLoc(); } else { @@ -13217,7 +13455,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, } if (!isTemplateInstantiation(TSK)) - return; + return; // Instantiate, but do not mark as odr-used, variable templates. MarkODRUsed = false; @@ -13316,7 +13554,8 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, if (!MD) return; // Only attempt to devirtualize if this is truly a virtual call. - bool IsVirtualCall = MD->isVirtual() && !ME->hasQualifier(); + bool IsVirtualCall = MD->isVirtual() && + ME->performsVirtualDispatch(SemaRef.getLangOpts()); if (!IsVirtualCall) return; const Expr *Base = ME->getBase(); @@ -13350,7 +13589,7 @@ void Sema::MarkMemberReferenced(MemberExpr *E) { // expression, is odr-used, unless it is a pure virtual function and its // name is not explicitly qualified. bool OdrUse = true; - if (!E->hasQualifier()) { + if (E->performsVirtualDispatch(getLangOpts())) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) if (Method->isPure()) OdrUse = false; @@ -13633,7 +13872,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { Diag(Loc, diagnostic) << E->getSourceRange(); SourceLocation Open = E->getLocStart(); - SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); + SourceLocation Close = getLocForEndOfToken(E->getSourceRange().getEnd()); Diag(Loc, diag::note_condition_assign_silence) << FixItHint::CreateInsertion(Open, "(") << FixItHint::CreateInsertion(Close, ")"); @@ -14309,6 +14548,11 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { return ExprError(); } + // Expressions of unknown type. + case BuiltinType::OMPArraySection: + Diag(E->getLocStart(), diag::err_omp_array_section_use); + return ExprError(); + // Everything else should be impossible. #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 9ad5aa5..2ad595f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -1031,6 +1031,11 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc); } + // C++14 [expr.type.conv]p2: The expression T(), where T is a + // simple-type-specifier or typename-specifier for a non-array complete + // object type or the (possibly cv-qualified) void type, creates a prvalue + // of the specified type, whose value is that produced by value-initializing + // an object of type T. QualType ElemTy = Ty; if (Ty->isArrayType()) { if (!ListInitialization) @@ -1039,6 +1044,10 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, ElemTy = Context.getBaseElementType(Ty); } + if (!ListInitialization && Ty->isFunctionType()) + return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_function_type) + << FullRange); + if (!Ty->isVoidType() && RequireCompleteType(TyBeginLoc, ElemTy, diag::err_invalid_incomplete_type_use, FullRange)) @@ -2256,6 +2265,9 @@ FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc, "found an unexpected usual deallocation function"); } + if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads) + EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches); + assert(Matches.size() == 1 && "unexpectedly have multiple usual deallocation functions"); return Matches.front(); @@ -2287,6 +2299,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, Matches.push_back(F.getPair()); } + if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads) + EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches); + // There's exactly one suitable operator; pick it. if (Matches.size() == 1) { Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl()); @@ -2702,6 +2717,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return ExprError(Diag(StartLoc, diag::err_delete_operand) << Type << Ex.get()->getSourceRange()); } else if (!Pointee->isDependentType()) { + // FIXME: This can result in errors if the definition was imported from a + // module but is hidden. if (!RequireCompleteType(StartLoc, Pointee, diag::warn_delete_incomplete, Ex.get())) { if (const RecordType *RT = PointeeElem->getAs<RecordType>()) @@ -2712,7 +2729,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (Pointee->isArrayType() && !ArrayForm) { Diag(StartLoc, diag::warn_delete_array_type) << Type << Ex.get()->getSourceRange() - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]"); + << FixItHint::CreateInsertion(getLocForEndOfToken(StartLoc), "[]"); ArrayForm = true; } @@ -2777,7 +2794,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (!OperatorDelete) // Look for a global declaration. OperatorDelete = FindUsualDeallocationFunction( - StartLoc, !RequireCompleteType(StartLoc, Pointee, 0) && + StartLoc, isCompleteType(StartLoc, Pointee) && (!ArrayForm || UsualArrayDeleteWantsSize || Pointee.isDestructedType()), DeleteName); @@ -3103,6 +3120,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ToType = ToAtomic->getValueType(); } + QualType InitialFromType = FromType; // Perform the first implicit conversion. switch (SCS.First) { case ICK_Identity: @@ -3293,8 +3311,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // We may not have been able to figure out what this member pointer resolved // to up until this exact point. Attempt to lock-in it's inheritance model. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - RequireCompleteType(From->getExprLoc(), From->getType(), 0); - RequireCompleteType(From->getExprLoc(), ToType, 0); + (void)isCompleteType(From->getExprLoc(), From->getType()); + (void)isCompleteType(From->getExprLoc(), ToType); } From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) @@ -3432,6 +3450,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, case ICK_Function_To_Pointer: case ICK_Qualification: case ICK_Num_Conversion_Kinds: + case ICK_C_Only_Conversion: llvm_unreachable("Improper second standard conversion"); } @@ -3472,6 +3491,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, VK_RValue, nullptr, CCK).get(); } + // If this conversion sequence succeeded and involved implicitly converting a + // _Nullable type to a _Nonnull one, complain. + if (CCK == CCK_ImplicitConversion) + diagnoseNullableToNonnullConversion(ToType, InitialFromType, + From->getLocStart()); + return From; } @@ -3534,27 +3559,43 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsVolatile: case UTT_IsSigned: case UTT_IsUnsigned: + + // This type trait always returns false, checking the type is moot. + case UTT_IsInterfaceClass: + return true; + + // C++14 [meta.unary.prop]: + // If T is a non-union class type, T shall be a complete type. + case UTT_IsEmpty: + case UTT_IsPolymorphic: + case UTT_IsAbstract: + if (const auto *RD = ArgTy->getAsCXXRecordDecl()) + if (!RD->isUnion()) + return !S.RequireCompleteType( + Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr); + return true; + + // C++14 [meta.unary.prop]: + // If T is a class type, T shall be a complete type. + case UTT_IsFinal: + case UTT_IsSealed: + if (ArgTy->getAsCXXRecordDecl()) + return !S.RequireCompleteType( + Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr); return true; - // C++0x [meta.unary.prop] Table 49 requires the following traits to be - // applied to a complete type. + // C++0x [meta.unary.prop] Table 49 requires the following traits to be + // applied to a complete type. case UTT_IsTrivial: case UTT_IsTriviallyCopyable: case UTT_IsStandardLayout: case UTT_IsPOD: case UTT_IsLiteral: - case UTT_IsEmpty: - case UTT_IsPolymorphic: - case UTT_IsAbstract: - case UTT_IsInterfaceClass: + case UTT_IsDestructible: case UTT_IsNothrowDestructible: // Fall-through - // These traits require a complete type. - case UTT_IsFinal: - case UTT_IsSealed: - // These trait expressions are designed to help implement predicates in // [meta.unary.prop] despite not being named the same. They are specified // by both GCC and the Embarcadero C++ compiler, and require the complete @@ -3698,39 +3739,36 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, case UTT_IsVolatile: return T.isVolatileQualified(); case UTT_IsTrivial: - return T.isTrivialType(Self.Context); + return T.isTrivialType(C); case UTT_IsTriviallyCopyable: - return T.isTriviallyCopyableType(Self.Context); + return T.isTriviallyCopyableType(C); case UTT_IsStandardLayout: return T->isStandardLayoutType(); case UTT_IsPOD: - return T.isPODType(Self.Context); + return T.isPODType(C); case UTT_IsLiteral: - return T->isLiteralType(Self.Context); + return T->isLiteralType(C); case UTT_IsEmpty: if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return !RD->isUnion() && RD->isEmpty(); return false; case UTT_IsPolymorphic: if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) - return RD->isPolymorphic(); + return !RD->isUnion() && RD->isPolymorphic(); return false; case UTT_IsAbstract: if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) - return RD->isAbstract(); + return !RD->isUnion() && RD->isAbstract(); return false; + // __is_interface_class only returns true when CL is invoked in /CLR mode and + // even then only when it is used with the 'interface struct ...' syntax + // Clang doesn't support /CLR which makes this type trait moot. case UTT_IsInterfaceClass: - if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) - return RD->isInterface(); return false; case UTT_IsFinal: - if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) - return RD->hasAttr<FinalAttr>(); - return false; case UTT_IsSealed: if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) - if (FinalAttr *FA = RD->getAttr<FinalAttr>()) - return FA->isSpelledAsSealed(); + return RD->hasAttr<FinalAttr>(); return false; case UTT_IsSigned: return T->isSignedIntegerType(); @@ -3757,7 +3795,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, // If __is_pod (type) is true then the trait is true, else if type is // a cv class or union type (or array thereof) with a trivial default // constructor ([class.ctor]) then the trait is true, else it is false. - if (T.isPODType(Self.Context)) + if (T.isPODType(C)) return true; if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) return RD->hasTrivialDefaultConstructor() && @@ -3767,7 +3805,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, // This trait is implemented by MSVC 2012 and needed to parse the // standard library headers. Specifically this is used as the logic // behind std::is_trivially_move_constructible (20.9.4.3). - if (T.isPODType(Self.Context)) + if (T.isPODType(C)) return true; if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor(); @@ -3778,7 +3816,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, // the trait is true, else if type is a cv class or union type // with a trivial copy constructor ([class.copy]) then the trait // is true, else it is false. - if (T.isPODType(Self.Context) || T->isReferenceType()) + if (T.isPODType(C) || T->isReferenceType()) return true; if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return RD->hasTrivialCopyConstructor() && @@ -3788,7 +3826,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, // This trait is implemented by MSVC 2012 and needed to parse the // standard library headers. Specifically it is used as the logic // behind std::is_trivially_move_assignable (20.9.4.3) - if (T.isPODType(Self.Context)) + if (T.isPODType(C)) return true; if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment(); @@ -3808,7 +3846,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, if (T.isConstQualified()) return false; - if (T.isPODType(Self.Context)) + if (T.isPODType(C)) return true; if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return RD->hasTrivialCopyAssignment() && @@ -3816,8 +3854,47 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return false; case UTT_IsDestructible: case UTT_IsNothrowDestructible: - // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible. - // For now, let's fall through. + // C++14 [meta.unary.prop]: + // For reference types, is_destructible<T>::value is true. + if (T->isReferenceType()) + return true; + + // Objective-C++ ARC: autorelease types don't require destruction. + if (T->isObjCLifetimeType() && + T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) + return true; + + // C++14 [meta.unary.prop]: + // For incomplete types and function types, is_destructible<T>::value is + // false. + if (T->isIncompleteType() || T->isFunctionType()) + return false; + + // C++14 [meta.unary.prop]: + // For object types and given U equal to remove_all_extents_t<T>, if the + // expression std::declval<U&>().~U() is well-formed when treated as an + // unevaluated operand (Clause 5), then is_destructible<T>::value is true + if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) { + CXXDestructorDecl *Destructor = Self.LookupDestructor(RD); + if (!Destructor) + return false; + // C++14 [dcl.fct.def.delete]p2: + // A program that refers to a deleted function implicitly or + // explicitly, other than to declare it, is ill-formed. + if (Destructor->isDeleted()) + return false; + if (C.getLangOpts().AccessControl && Destructor->getAccess() != AS_public) + return false; + if (UTT == UTT_IsNothrowDestructible) { + const FunctionProtoType *CPT = + Destructor->getType()->getAs<FunctionProtoType>(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT || !CPT->isNothrow(C)) + return false; + } + } + return true; + case UTT_HasTrivialDestructor: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html // If __is_pod (type) is true or type is a reference type @@ -3825,7 +3902,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, // type (or array thereof) with a trivial destructor // ([class.dtor]) then the trait is true, else it is // false. - if (T.isPODType(Self.Context) || T->isReferenceType()) + if (T.isPODType(C) || T->isReferenceType()) return true; // Objective-C++ ARC: autorelease types don't require destruction. @@ -3849,7 +3926,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return false; if (T->isReferenceType()) return false; - if (T.isPODType(Self.Context) || T->isObjCLifetimeType()) + if (T.isPODType(C) || T->isObjCLifetimeType()) return true; if (const RecordType *RT = T->getAs<RecordType>()) @@ -3862,7 +3939,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, // This trait is implemented by MSVC 2012 and needed to parse the // standard library headers. Specifically this is used as the logic // behind std::is_nothrow_move_assignable (20.9.4.3). - if (T.isPODType(Self.Context)) + if (T.isPODType(C)) return true; if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) @@ -3886,15 +3963,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, bool FoundConstructor = false; unsigned FoundTQs; - DeclContext::lookup_result R = Self.LookupConstructors(RD); - for (DeclContext::lookup_iterator Con = R.begin(), - ConEnd = R.end(); Con != ConEnd; ++Con) { + for (const auto *ND : Self.LookupConstructors(RD)) { // A template constructor is never a copy constructor. // FIXME: However, it may actually be selected at the actual overload // resolution point. - if (isa<FunctionTemplateDecl>(*Con)) + if (isa<FunctionTemplateDecl>(ND)) continue; - CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); + const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND); if (Constructor->isCopyConstructor(FoundTQs)) { FoundConstructor = true; const FunctionProtoType *CPT @@ -3904,7 +3979,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return false; // TODO: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. - if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 1) + if (!CPT->isNothrow(C) || CPT->getNumParams() > 1) return false; } } @@ -3926,13 +4001,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return true; bool FoundConstructor = false; - DeclContext::lookup_result R = Self.LookupConstructors(RD); - for (DeclContext::lookup_iterator Con = R.begin(), - ConEnd = R.end(); Con != ConEnd; ++Con) { + for (const auto *ND : Self.LookupConstructors(RD)) { // FIXME: In C++0x, a constructor template can be a default constructor. - if (isa<FunctionTemplateDecl>(*Con)) + if (isa<FunctionTemplateDecl>(ND)) continue; - CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); + const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND); if (Constructor->isDefaultConstructor()) { FoundConstructor = true; const FunctionProtoType *CPT @@ -3942,7 +4015,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return false; // FIXME: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. - if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 0) + if (!CPT->isNothrow(C) || CPT->getNumParams() > 0) return false; } } @@ -4023,8 +4096,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, // Precondition: T and all types in the parameter pack Args shall be // complete types, (possibly cv-qualified) void, or arrays of // unknown bound. - for (unsigned I = 0, N = Args.size(); I != N; ++I) { - QualType ArgTy = Args[I]->getType(); + for (const auto *TSI : Args) { + QualType ArgTy = TSI->getType(); if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType()) continue; @@ -4033,12 +4106,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, return false; } - // Make sure the first argument is a complete type. - if (Args[0]->getType()->isIncompleteType()) + // Make sure the first argument is not incomplete nor a function type. + QualType T = Args[0]->getType(); + if (T->isIncompleteType() || T->isFunctionType()) return false; // Make sure the first argument is not an abstract type. - CXXRecordDecl *RD = Args[0]->getType()->getAsCXXRecordDecl(); + CXXRecordDecl *RD = T->getAsCXXRecordDecl(); if (RD && RD->isAbstract()) return false; @@ -4046,13 +4120,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, SmallVector<Expr *, 2> ArgExprs; ArgExprs.reserve(Args.size() - 1); for (unsigned I = 1, N = Args.size(); I != N; ++I) { - QualType T = Args[I]->getType(); - if (T->isObjectType() || T->isFunctionType()) - T = S.Context.getRValueReferenceType(T); + QualType ArgTy = Args[I]->getType(); + if (ArgTy->isObjectType() || ArgTy->isFunctionType()) + ArgTy = S.Context.getRValueReferenceType(ArgTy); OpaqueArgExprs.push_back( - OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(), - T.getNonLValueExprType(S.Context), - Expr::getValueKindForType(T))); + OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(), + ArgTy.getNonLValueExprType(S.Context), + Expr::getValueKindForType(ArgTy))); } for (Expr &E : OpaqueArgExprs) ArgExprs.push_back(&E); @@ -4083,7 +4157,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, // Under Objective-C ARC, if the destination has non-trivial Objective-C // lifetime, this is a non-trivial construction. if (S.getLangOpts().ObjCAutoRefCount && - hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType())) + hasNontrivialObjCLifetime(T.getNonReferenceType())) return false; // The initialization succeeded; now make sure there are no non-trivial @@ -4219,8 +4293,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, return LhsT->isVoidType(); // A function definition requires a complete, non-abstract return type. - if (Self.RequireCompleteType(KeyLoc, RhsT, 0) || - Self.RequireNonAbstractType(KeyLoc, RhsT, 0)) + if (!Self.isCompleteType(KeyLoc, RhsT) || Self.isAbstractType(KeyLoc, RhsT)) return false; // Compute the result of add_rvalue_reference. @@ -4506,7 +4579,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); } - if (!IsDerivedFrom(LHSType, Class)) { + if (!IsDerivedFrom(Loc, LHSType, Class)) { Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling << (int)isIndirect << LHS.get()->getType(); return QualType(); @@ -4634,9 +4707,9 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, const RecordType *FRec = FTy->getAs<RecordType>(); const RecordType *TRec = TTy->getAs<RecordType>(); bool FDerivedFromT = FRec && TRec && FRec != TRec && - Self.IsDerivedFrom(FTy, TTy); - if (FRec && TRec && - (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) { + Self.IsDerivedFrom(QuestionLoc, FTy, TTy); + if (FRec && TRec && (FRec == TRec || FDerivedFromT || + Self.IsDerivedFrom(QuestionLoc, TTy, FTy))) { // E1 can be converted to match E2 if the class of T2 is the // same type as, or a base class of, the class of T1, and // [cv2 > cv1]. @@ -5671,9 +5744,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // // This also indicates that we could be parsing a pseudo-destructor-name. // Note that Objective-C class and object types can be pseudo-destructor - // expressions or normal member (ivar or property) access expressions. + // expressions or normal member (ivar or property) access expressions, and + // it's legal for the type to be incomplete if this is a pseudo-destructor + // call. We'll do more incomplete-type checks later in the lookup process, + // so just skip this check for ObjC types. if (BaseType->isObjCObjectOrInterfaceType()) { + ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; + return Base; } else if (!BaseType->isRecordType()) { ObjectType = ParsedType(); MayBePseudoDestructor = true; @@ -6331,7 +6409,7 @@ static ExprResult attemptRecovery(Sema &SemaRef, else if (SS && !TC.WillReplaceSpecifier()) NewSS = *SS; - if (auto *ND = TC.getCorrectionDecl()) { + if (auto *ND = TC.getFoundDecl()) { R.setLookupName(ND->getDeclName()); R.addDecl(ND); if (ND->isCXXClassMember()) { @@ -6364,7 +6442,7 @@ static ExprResult attemptRecovery(Sema &SemaRef, if (MightBeImplicitMember) return SemaRef.BuildPossibleImplicitMemberExpr( NewSS, /*TemplateKWLoc*/ SourceLocation(), R, - /*TemplateArgs*/ nullptr); + /*TemplateArgs*/ nullptr, /*S*/ nullptr); } else if (auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { return SemaRef.LookupInObjCMethod(R, Consumer.getScope(), Ivar->getIdentifier()); @@ -6452,9 +6530,9 @@ class TransformTypos : public TreeTransform<TransformTypos> { if (!E) return nullptr; if (auto *DRE = dyn_cast<DeclRefExpr>(E)) - return DRE->getDecl(); + return DRE->getFoundDecl(); if (auto *ME = dyn_cast<MemberExpr>(E)) - return ME->getMemberDecl(); + return ME->getFoundDecl(); // FIXME: Add any other expr types that could be be seen by the delayed typo // correction TreeTransform for which the corresponding TypoCorrection could // contain multiple decls. @@ -6494,6 +6572,8 @@ public: ExprResult TransformLambdaExpr(LambdaExpr *E) { return Owned(E); } + ExprResult TransformBlockExpr(BlockExpr *E) { return Owned(E); } + ExprResult Transform(Expr *E) { ExprResult Res; while (true) { @@ -6557,7 +6637,7 @@ 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) + if (InitDecl && TC.getFoundDecl() == InitDecl) continue; ExprResult NE = State.RecoveryHandler ? State.RecoveryHandler(SemaRef, E, TC) : diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp index a9f1919..9c345f8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp @@ -27,18 +27,15 @@ using namespace clang; using namespace sema; typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet; -static bool BaseIsNotInSet(const CXXRecordDecl *Base, void *BasesPtr) { - const BaseSet &Bases = *reinterpret_cast<const BaseSet*>(BasesPtr); - return !Bases.count(Base->getCanonicalDecl()); -} /// Determines if the given class is provably not derived from all of /// the prospective base classes. static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record, const BaseSet &Bases) { - void *BasesPtr = const_cast<void*>(reinterpret_cast<const void*>(&Bases)); - return BaseIsNotInSet(Record, BasesPtr) && - Record->forallBases(BaseIsNotInSet, BasesPtr); + auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) { + return !Bases.count(Base->getCanonicalDecl()); + }; + return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet); } enum IMAKind { @@ -105,8 +102,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, bool hasNonInstance = false; bool isField = false; BaseSet Classes; - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { - NamedDecl *D = *I; + for (NamedDecl *D : R) { + // Look through any using decls. + D = D->getUnderlyingDecl(); if (D->isCXXInstanceMember()) { isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || @@ -114,8 +112,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); Classes.insert(R->getCanonicalDecl()); - } - else + } else hasNonInstance = true; } @@ -237,15 +234,17 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + const Scope *S) { switch (ClassifyImplicitMemberAccess(*this, R)) { case IMA_Instance: - return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true); + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S); case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: - return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false); + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false, + S); case IMA_Field_Uneval_Context: Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) @@ -633,6 +632,16 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, DeclarationName Typo = R.getLookupName(); SourceLocation TypoLoc = R.getNameLoc(); + + struct QueryState { + Sema &SemaRef; + DeclarationNameInfo NameInfo; + Sema::LookupNameKind LookupKind; + Sema::RedeclarationKind Redecl; + }; + QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(), + R.isForRedeclaration() ? Sema::ForRedeclaration + : Sema::NotForRedeclaration}; TE = SemaRef.CorrectTypoDelayed( R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, llvm::make_unique<RecordMemberExprValidatorCCC>(RTy), @@ -651,6 +660,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, } }, [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable { + LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl); R.clear(); // Ensure there's no decls lingering in the shared state. R.suppressDiagnostics(); R.setLookupName(TC.getCorrection()); @@ -659,7 +669,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, R.resolveKind(); return SemaRef.BuildMemberReferenceExpr( BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(), - nullptr, R, nullptr); + nullptr, R, nullptr, nullptr); }, Sema::CTK_ErrorRecovery, DC); @@ -679,6 +689,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, + const Scope *S, ActOnMemberAccessExtraArgs *ExtraArgs) { if (BaseType->isDependentType() || (SS.isSet() && isDependentScopeSpecifier(SS))) @@ -725,7 +736,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, return BuildMemberReferenceExpr(Base, BaseType, OpLoc, IsArrow, SS, TemplateKWLoc, - FirstQualifierInScope, R, TemplateArgs, + FirstQualifierInScope, R, TemplateArgs, S, false, ExtraArgs); } @@ -877,6 +888,18 @@ static MemberExpr *BuildMemberExpr( return E; } +/// \brief Determine if the given scope is within a function-try-block handler. +static bool IsInFnTryBlockHandler(const Scope *S) { + // Walk the scope stack until finding a FnTryCatchScope, or leave the + // function scope. If a FnTryCatchScope is found, check whether the TryScope + // flag is set. If it is not, it's a function-try-block handler. + for (; S != S->getFnParent(); S = S->getParent()) { + if (S->getFlags() & Scope::FnTryCatchScope) + return (S->getFlags() & Scope::TryScope) != Scope::TryScope; + } + return false; +} + ExprResult Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation OpLoc, bool IsArrow, @@ -885,6 +908,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, NamedDecl *FirstQualifierInScope, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, + const Scope *S, bool SuppressQualifierCheck, ActOnMemberAccessExtraArgs *ExtraArgs) { QualType BaseType = BaseExprType; @@ -948,6 +972,17 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (R.isAmbiguous()) return ExprError(); + // [except.handle]p10: Referring to any non-static member or base class of an + // object in the handler for a function-try-block of a constructor or + // destructor for that object results in undefined behavior. + const auto *FD = getCurFunctionDecl(); + if (S && BaseExpr && FD && + (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) && + isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) && + IsInFnTryBlockHandler(S)) + Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr) + << isa<CXXDestructorDecl>(FD); + if (R.empty()) { // Rederive where we looked up. DeclContext *DC = (SS.isSet() @@ -1042,16 +1077,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true); } - bool ShouldCheckUse = true; - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) { - // Don't diagnose the use of a virtual member function unless it's - // explicitly qualified. - if (MD->isVirtual() && !SS.isSet()) - ShouldCheckUse = false; - } - // Check the use of this member. - if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) + if (DiagnoseUseOfDecl(MemberDecl, MemberLoc)) return ExprError(); if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) @@ -1645,7 +1672,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, FirstQualifierInScope, - NameInfo, TemplateArgs, &ExtraArgs); + NameInfo, TemplateArgs, S, &ExtraArgs); } static ExprResult @@ -1718,7 +1745,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, - bool IsKnownInstance) { + bool IsKnownInstance, const Scope *S) { assert(!R.empty() && !R.isAmbiguous()); SourceLocation loc = R.getNameLoc(); @@ -1743,5 +1770,5 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, /*IsArrow*/ true, SS, TemplateKWLoc, /*FirstQualifierInScope*/ nullptr, - R, TemplateArgs); + R, TemplateArgs, S); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index 6cd0626..65f1081 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -32,24 +32,21 @@ using namespace sema; using llvm::makeArrayRef; ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, - Expr **strings, - unsigned NumStrings) { - StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings); - + ArrayRef<Expr *> Strings) { // Most ObjC strings are formed out of a single piece. However, we *can* // have strings formed out of multiple @ strings with multiple pptokens in // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one // StringLiteral for ObjCStringLiteral to hold onto. - StringLiteral *S = Strings[0]; + StringLiteral *S = cast<StringLiteral>(Strings[0]); // If we have a multi-part string, merge it all together. - if (NumStrings != 1) { + if (Strings.size() != 1) { // Concatenate objc strings. SmallString<128> StrBuf; SmallVector<SourceLocation, 8> StrLocs; - for (unsigned i = 0; i != NumStrings; ++i) { - S = Strings[i]; + for (Expr *E : Strings) { + S = cast<StringLiteral>(E); // ObjC strings can't be wide or UTF. if (!S->isAscii()) { @@ -168,6 +165,77 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc, return true; } +/// \brief Maps ObjCLiteralKind to NSClassIdKindKind +static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind( + Sema::ObjCLiteralKind LiteralKind) { + switch (LiteralKind) { + case Sema::LK_Array: + return NSAPI::ClassId_NSArray; + case Sema::LK_Dictionary: + return NSAPI::ClassId_NSDictionary; + case Sema::LK_Numeric: + return NSAPI::ClassId_NSNumber; + case Sema::LK_String: + return NSAPI::ClassId_NSString; + case Sema::LK_Boxed: + return NSAPI::ClassId_NSValue; + + // there is no corresponding matching + // between LK_None/LK_Block and NSClassIdKindKind + case Sema::LK_Block: + case Sema::LK_None: + break; + } + llvm_unreachable("LiteralKind can't be converted into a ClassKind"); +} + +/// \brief Validates ObjCInterfaceDecl availability. +/// ObjCInterfaceDecl, used to create ObjC literals, should be defined +/// if clang not in a debugger mode. +static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl, + SourceLocation Loc, + Sema::ObjCLiteralKind LiteralKind) { + if (!Decl) { + NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind); + IdentifierInfo *II = S.NSAPIObj->getNSClassId(Kind); + S.Diag(Loc, diag::err_undeclared_objc_literal_class) + << II->getName() << LiteralKind; + return false; + } else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) { + S.Diag(Loc, diag::err_undeclared_objc_literal_class) + << Decl->getName() << LiteralKind; + S.Diag(Decl->getLocation(), diag::note_forward_class); + return false; + } + + return true; +} + +/// \brief Looks up ObjCInterfaceDecl of a given NSClassIdKindKind. +/// Used to create ObjC literals, such as NSDictionary (@{}), +/// NSArray (@[]) and Boxed Expressions (@()) +static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S, + SourceLocation Loc, + Sema::ObjCLiteralKind LiteralKind) { + NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind); + IdentifierInfo *II = S.NSAPIObj->getNSClassId(ClassKind); + NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc, + Sema::LookupOrdinaryName); + ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + if (!ID && S.getLangOpts().DebuggerObjCLiteral) { + ASTContext &Context = S.Context; + TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II, + nullptr, nullptr, SourceLocation()); + } + + if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) { + ID = nullptr; + } + + return ID; +} + /// \brief Retrieve the NSNumber factory method that should be used to create /// an Objective-C literal for the given type. static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, @@ -197,26 +265,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, // Look up the NSNumber class, if we haven't done so already. It's cached // in the Sema instance. if (!S.NSNumberDecl) { - IdentifierInfo *NSNumberId = - S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber); - NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId, - Loc, Sema::LookupOrdinaryName); - S.NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + S.NSNumberDecl = LookupObjCInterfaceDeclForLiteral(S, Loc, + Sema::LK_Numeric); if (!S.NSNumberDecl) { - if (S.getLangOpts().DebuggerObjCLiteral) { - // Create a stub definition of NSNumber. - S.NSNumberDecl = ObjCInterfaceDecl::Create(CX, - CX.getTranslationUnitDecl(), - SourceLocation(), NSNumberId, - nullptr, nullptr, - SourceLocation()); - } else { - // Otherwise, require a declaration of NSNumber. - S.Diag(Loc, diag::err_undeclared_nsnumber); - return nullptr; - } - } else if (!S.NSNumberDecl->hasDefinition()) { - S.Diag(Loc, diag::err_undeclared_nsnumber); return nullptr; } } @@ -457,6 +508,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { if (RValue.isInvalid()) { return ExprError(); } + SourceLocation Loc = SR.getBegin(); ValueExpr = RValue.get(); QualType ValueType(ValueExpr->getType()); if (const PointerType *PT = ValueType->getAs<PointerType>()) { @@ -464,29 +516,11 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) { if (!NSStringDecl) { - IdentifierInfo *NSStringId = - NSAPIObj->getNSClassId(NSAPI::ClassId_NSString); - NamedDecl *Decl = LookupSingleName(TUScope, NSStringId, - SR.getBegin(), LookupOrdinaryName); - NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl); + NSStringDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, + Sema::LK_String); if (!NSStringDecl) { - if (getLangOpts().DebuggerObjCLiteral) { - // Support boxed expressions in the debugger w/o NSString declaration. - DeclContext *TU = Context.getTranslationUnitDecl(); - NSStringDecl = ObjCInterfaceDecl::Create(Context, TU, - SourceLocation(), - NSStringId, - nullptr, nullptr, - SourceLocation()); - } else { - Diag(SR.getBegin(), diag::err_undeclared_nsstring); - return ExprError(); - } - } else if (!NSStringDecl->hasDefinition()) { - Diag(SR.getBegin(), diag::err_undeclared_nsstring); return ExprError(); } - assert(NSStringDecl && "NSStringDecl should not be NULL"); QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl); NSStringPointer = Context.getObjCObjectPointerType(NSStringObject); } @@ -520,7 +554,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { BoxingMethod = M; } - if (!validateBoxingMethod(*this, SR.getBegin(), NSStringDecl, + if (!validateBoxingMethod(*this, Loc, NSStringDecl, stringWithUTF8String, BoxingMethod)) return ExprError(); @@ -563,16 +597,16 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { // FIXME: Do I need to do anything special with BoolTy expressions? // Look for the appropriate method within NSNumber. - BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType); + BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType); BoxedType = NSNumberPointer; } else if (const EnumType *ET = ValueType->getAs<EnumType>()) { if (!ET->getDecl()->isComplete()) { - Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type) + Diag(Loc, diag::err_objc_incomplete_boxed_expression_type) << ValueType << ValueExpr->getSourceRange(); return ExprError(); } - BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), + BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ET->getDecl()->getIntegerType()); BoxedType = NSNumberPointer; } else if (ValueType->isObjCBoxableRecordType()) { @@ -582,29 +616,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { // Look up the NSValue class, if we haven't done so already. It's cached // in the Sema instance. if (!NSValueDecl) { - IdentifierInfo *NSValueId = - NSAPIObj->getNSClassId(NSAPI::ClassId_NSValue); - NamedDecl *IF = LookupSingleName(TUScope, NSValueId, - SR.getBegin(), Sema::LookupOrdinaryName); - NSValueDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); + NSValueDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, + Sema::LK_Boxed); if (!NSValueDecl) { - if (getLangOpts().DebuggerObjCLiteral) { - // Create a stub definition of NSValue. - DeclContext *TU = Context.getTranslationUnitDecl(); - NSValueDecl = ObjCInterfaceDecl::Create(Context, TU, - SourceLocation(), NSValueId, - nullptr, nullptr, - SourceLocation()); - } else { - // Otherwise, require a declaration of NSValue. - Diag(SR.getBegin(), diag::err_undeclared_nsvalue); - return ExprError(); - } - } else if (!NSValueDecl->hasDefinition()) { - Diag(SR.getBegin(), diag::err_undeclared_nsvalue); return ExprError(); } - + // generate the pointer to NSValue type. QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl); NSValuePointer = Context.getObjCObjectPointerType(NSValueObject); @@ -663,7 +680,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { BoxingMethod = M; } - if (!validateBoxingMethod(*this, SR.getBegin(), NSValueDecl, + if (!validateBoxingMethod(*this, Loc, NSValueDecl, ValueWithBytesObjCType, BoxingMethod)) return ExprError(); @@ -671,8 +688,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { } if (!ValueType.isTriviallyCopyableType(Context)) { - Diag(SR.getBegin(), - diag::err_objc_non_trivially_copyable_boxed_expression_type) + Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type) << ValueType << ValueExpr->getSourceRange(); return ExprError(); } @@ -682,12 +698,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { } if (!BoxingMethod) { - Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type) + Diag(Loc, diag::err_objc_illegal_boxed_expression_type) << ValueType << ValueExpr->getSourceRange(); return ExprError(); } - DiagnoseUseOfDecl(BoxingMethod, SR.getBegin()); + DiagnoseUseOfDecl(BoxingMethod, Loc); ExprResult ConvertedValueExpr; if (ValueType->isObjCBoxableRecordType()) { @@ -746,26 +762,16 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, } ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { - // Look up the NSArray class, if we haven't done so already. - if (!NSArrayDecl) { - NamedDecl *IF = LookupSingleName(TUScope, - NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), - SR.getBegin(), - LookupOrdinaryName); - NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); - if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral) - NSArrayDecl = ObjCInterfaceDecl::Create (Context, - Context.getTranslationUnitDecl(), - SourceLocation(), - NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), - nullptr, nullptr, SourceLocation()); + SourceLocation Loc = SR.getBegin(); + if (!NSArrayDecl) { + NSArrayDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, + Sema::LK_Array); if (!NSArrayDecl) { - Diag(SR.getBegin(), diag::err_undeclared_nsarray); return ExprError(); } } - + // Find the arrayWithObjects:count: method, if we haven't done so already. QualType IdT = Context.getObjCIdType(); if (!ArrayWithObjectsMethod) { @@ -801,7 +807,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { Method->setMethodParams(Context, Params, None); } - if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method)) + if (!validateBoxingMethod(*this, Loc, NSArrayDecl, Sel, Method)) return ExprError(); // Dig out the type that all elements should be converted to. @@ -859,28 +865,18 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { ArrayWithObjectsMethod, SR)); } -ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, - ObjCDictionaryElement *Elements, - unsigned NumElements) { - // Look up the NSDictionary class, if we haven't done so already. - if (!NSDictionaryDecl) { - NamedDecl *IF = LookupSingleName(TUScope, - NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), - SR.getBegin(), LookupOrdinaryName); - NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); - if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral) - NSDictionaryDecl = ObjCInterfaceDecl::Create (Context, - Context.getTranslationUnitDecl(), - SourceLocation(), - NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), - nullptr, nullptr, SourceLocation()); +ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, + MutableArrayRef<ObjCDictionaryElement> Elements) { + SourceLocation Loc = SR.getBegin(); + if (!NSDictionaryDecl) { + NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, + Sema::LK_Dictionary); if (!NSDictionaryDecl) { - Diag(SR.getBegin(), diag::err_undeclared_nsdictionary); - return ExprError(); + return ExprError(); } } - + // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done // so already. QualType IdT = Context.getObjCIdType(); @@ -1007,31 +1003,31 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, // Check that each of the keys and values provided is valid in a collection // literal, performing conversions as necessary. bool HasPackExpansions = false; - for (unsigned I = 0, N = NumElements; I != N; ++I) { + for (ObjCDictionaryElement &Element : Elements) { // Check the key. - ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key, + ExprResult Key = CheckObjCCollectionLiteralElement(*this, Element.Key, KeyT); if (Key.isInvalid()) return ExprError(); // Check the value. ExprResult Value - = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT); + = CheckObjCCollectionLiteralElement(*this, Element.Value, ValueT); if (Value.isInvalid()) return ExprError(); - Elements[I].Key = Key.get(); - Elements[I].Value = Value.get(); + Element.Key = Key.get(); + Element.Value = Value.get(); - if (Elements[I].EllipsisLoc.isInvalid()) + if (Element.EllipsisLoc.isInvalid()) continue; - if (!Elements[I].Key->containsUnexpandedParameterPack() && - !Elements[I].Value->containsUnexpandedParameterPack()) { - Diag(Elements[I].EllipsisLoc, + if (!Element.Key->containsUnexpandedParameterPack() && + !Element.Value->containsUnexpandedParameterPack()) { + Diag(Element.EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) - << SourceRange(Elements[I].Key->getLocStart(), - Elements[I].Value->getLocEnd()); + << SourceRange(Element.Key->getLocStart(), + Element.Value->getLocEnd()); return ExprError(); } @@ -1043,7 +1039,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, = Context.getObjCObjectPointerType( Context.getObjCInterfaceType(NSDictionaryDecl)); return MaybeBindToTemporary(ObjCDictionaryLiteral::Create( - Context, makeArrayRef(Elements, NumElements), HasPackExpansions, Ty, + Context, Elements, HasPackExpansions, Ty, DictionaryWithObjectsMethod, SR)); } @@ -1092,7 +1088,7 @@ ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, QualType EncodedType = GetTypeFromParser(ty, &TInfo); if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(EncodedType, - PP.getLocForEndOfToken(LParenLoc)); + getLocForEndOfToken(LParenLoc)); return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); } @@ -1657,7 +1653,8 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, // Objective-C pointer type, we may need to extend the lifetime // of the block object. if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() && - origParamType->isBlockCompatibleObjCPointerType(Context)) { + Args[i]->getType()->isBlockPointerType() && + origParamType->isObjCObjectPointerType()) { ExprResult arg = Args[i]; maybeExtendBlockObject(arg); Args[i] = arg.get(); @@ -1778,8 +1775,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, diag::err_property_not_found_forward_class, MemberName, BaseRange)) return ExprError(); - - // Search for a declared property first. + if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) @@ -2726,6 +2722,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // Try to complete the type. Under ARC, this is a hard error from which // we don't try to recover. + // FIXME: In the non-ARC case, this will still be a hard error if the + // definition is found in a module that's not visible. const ObjCInterfaceDecl *forwardClass = nullptr; if (RequireCompleteType(Loc, OCIType->getPointeeType(), getLangOpts().ObjCAutoRefCount @@ -3397,7 +3395,7 @@ static void addFixitForObjCARCConversion(Sema &S, DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), BridgeCall)); DiagB.AddFixItHint(FixItHint::CreateInsertion( - S.PP.getLocForEndOfToken(range.getEnd()), + S.getLocForEndOfToken(range.getEnd()), ")")); } return; @@ -3430,7 +3428,7 @@ static void addFixitForObjCARCConversion(Sema &S, DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), castCode)); DiagB.AddFixItHint(FixItHint::CreateInsertion( - S.PP.getLocForEndOfToken(range.getEnd()), + S.getLocForEndOfToken(range.getEnd()), ")")); } } @@ -3471,7 +3469,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc()); if (S.makeUnavailableInSystemHeader(loc, - "converts between Objective-C and C pointers in -fobjc-arc")) + UnavailableAttr::IR_ARCForbiddenConversion)) return; QualType castExprType = castExpr->getType(); @@ -3498,7 +3496,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, } // Check whether this could be fixed with a bridge cast. - SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin()); + SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin()); SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc; // Bridge from an ARC type to a CF type. @@ -3901,7 +3899,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, ExpressionString += RelatedClass->getNameAsString(); ExpressionString += " "; ExpressionString += ClassMethod->getSelector().getAsString(); - SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd()); + SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd()); // Provide a fixit: [RelatedClass ClassMethod SrcExpr] Diag(Loc, diag::err_objc_bridged_related_known_method) << SrcType << DestType << ClassMethod->getSelector() << false @@ -3926,7 +3924,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, // Implicit conversion from ObjC type to CF object is needed. if (InstanceMethod) { std::string ExpressionString; - SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd()); + SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd()); if (InstanceMethod->isPropertyAccessor()) if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) { // fixit: ObjectExpr.propertyname when it is aproperty accessor. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp index 2e327ec..714fbed 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp @@ -42,7 +42,7 @@ bool ConversionFixItGenerator::compareTypesSimple(CanQualType From, const CanQualType FromUnq = From.getUnqualifiedType(); const CanQualType ToUnq = To.getUnqualifiedType(); - if ((FromUnq == ToUnq || (S.IsDerivedFrom(FromUnq, ToUnq)) ) && + if ((FromUnq == ToUnq || (S.IsDerivedFrom(Loc, FromUnq, ToUnq)) ) && To.isAtLeastAsQualifiedAs(From)) return true; return false; @@ -58,8 +58,8 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr, const CanQualType FromQTy = S.Context.getCanonicalType(FromTy); const CanQualType ToQTy = S.Context.getCanonicalType(ToTy); const SourceLocation Begin = FullExpr->getSourceRange().getBegin(); - const SourceLocation End = S.PP.getLocForEndOfToken(FullExpr->getSourceRange() - .getEnd()); + const SourceLocation End = S.getLocForEndOfToken(FullExpr->getSourceRange() + .getEnd()); // Strip the implicit casts - those are implied by the compiler, not the // original source code. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index adec512..c3a8946 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -443,8 +443,11 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, if (!VerifyOnly) { SemaRef.Diag(CtorDecl->getLocation(), diag::warn_invalid_initializer_from_system_header); - SemaRef.Diag(Entity.getDecl()->getLocation(), - diag::note_used_in_initialization_here); + if (Entity.getKind() == InitializedEntity::EK_Member) + SemaRef.Diag(Entity.getDecl()->getLocation(), + diag::note_used_in_initialization_here); + else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) + SemaRef.Diag(Loc, diag::note_used_in_initialization_here); } } } @@ -802,7 +805,8 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); // Update the structured sub-object initializer so that it's ending // range corresponds with the end of the last initializer it used. - if (EndIndex < ParentIList->getNumInits()) { + if (EndIndex < ParentIList->getNumInits() && + ParentIList->getInit(EndIndex)) { SourceLocation EndLoc = ParentIList->getInit(EndIndex)->getSourceRange().getEnd(); StructuredSubobjectInitList->setRBraceLoc(EndLoc); @@ -3008,6 +3012,7 @@ bool InitializationSequence::isAmbiguous() const { case FK_VariableLengthArrayHasInitializer: case FK_PlaceholderType: case FK_ExplicitConstructor: + case FK_AddressOfUnaddressableFunction: return false; case FK_ReferenceInitOverloadFailed: @@ -3323,7 +3328,7 @@ static bool TryInitializerListConstruction(Sema &S, if (!S.isStdInitializerList(DestType, &E)) return false; - if (S.RequireCompleteType(List->getExprLoc(), E, 0)) { + if (!S.isCompleteType(List->getExprLoc(), E)) { Sequence.setIncompleteTypeFailure(E); return true; } @@ -3433,7 +3438,7 @@ static void TryConstructorInitialization(Sema &S, "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)) { + if (!S.isCompleteType(Kind.getLocation(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } @@ -3674,7 +3679,7 @@ static void TryListInitialization(Sema &S, } if (DestType->isRecordType() && - S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) { + !S.isCompleteType(InitList->getLocStart(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } @@ -3694,7 +3699,7 @@ static void TryListInitialization(Sema &S, if (DestType->isRecordType()) { QualType InitType = InitList->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, DestType) || - S.IsDerivedFrom(InitType, DestType)) { + S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) { Expr *InitAsExpr = InitList->getInit(0); TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType, Sequence, /*InitListSyntax*/ false, @@ -3728,7 +3733,9 @@ static void TryListInitialization(Sema &S, // C++11 [dcl.init.list]p3: // - If T is an aggregate, aggregate initialization is performed. - if (DestType->isRecordType() && !DestType->isAggregateType()) { + if ((DestType->isRecordType() && !DestType->isAggregateType()) || + (S.getLangOpts().CPlusPlus11 && + S.isStdInitializerList(DestType, nullptr))) { 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 @@ -3834,7 +3841,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const RecordType *T1RecordType = nullptr; if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) && - !S.RequireCompleteType(Kind.getLocation(), T1, 0)) { + S.isCompleteType(Kind.getLocation(), T1)) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl()); @@ -3870,7 +3877,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const RecordType *T2RecordType = nullptr; if ((T2RecordType = T2->getAs<RecordType>()) && - !S.RequireCompleteType(Kind.getLocation(), T2, 0)) { + S.isCompleteType(Kind.getLocation(), T2)) { // The type we're converting from is a class type, enumerate its conversion // functions. CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl()); @@ -4455,7 +4462,7 @@ static void TryUserDefinedConversion(Sema &S, = cast<CXXRecordDecl>(DestRecordType->getDecl()); // Try to complete the type we're converting to. - if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { + if (S.isCompleteType(Kind.getLocation(), DestType)) { DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl); // The container holding the constructors can under certain conditions // be changed while iterating. To be safe we copy the lookup results @@ -4501,7 +4508,7 @@ static void TryUserDefinedConversion(Sema &S, // We can only enumerate the conversion functions for a complete type; if // the type isn't complete, simply skip this step. - if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) { + if (S.isCompleteType(DeclLoc, SourceType)) { CXXRecordDecl *SourceRecordDecl = cast<CXXRecordDecl>(SourceRecordType->getDecl()); @@ -4798,6 +4805,17 @@ InitializationSequence::InitializationSequence(Sema &S, InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList); } +/// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the +/// address of that function, this returns true. Otherwise, it returns false. +static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) { + auto *DRE = dyn_cast<DeclRefExpr>(E); + if (!DRE || !isa<FunctionDecl>(DRE->getDecl())) + return false; + + return !S.checkAddressOfFunctionIsAvailable( + cast<FunctionDecl>(DRE->getDecl())); +} + void InitializationSequence::InitializeFrom(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -4979,7 +4997,7 @@ void InitializationSequence::InitializeFrom(Sema &S, } assert(S.getLangOpts().CPlusPlus); - + // - If the destination type is a (possibly cv-qualified) class type: if (DestType->isRecordType()) { // - If the initialization is direct-initialization, or if it is @@ -4989,7 +5007,7 @@ void InitializationSequence::InitializeFrom(Sema &S, if (Kind.getKind() == InitializationKind::IK_Direct || (Kind.getKind() == InitializationKind::IK_Copy && (Context.hasSameUnqualifiedType(SourceType, DestType) || - S.IsDerivedFrom(SourceType, DestType)))) + S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, DestType, *this); // - Otherwise (i.e., for the remaining copy-initialization cases), @@ -5018,7 +5036,8 @@ void InitializationSequence::InitializeFrom(Sema &S, bool NeedAtomicConversion = false; if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) { if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) || - S.IsDerivedFrom(SourceType, Atomic->getValueType())) { + S.IsDerivedFrom(Initializer->getLocStart(), SourceType, + Atomic->getValueType())) { DestType = Atomic->getValueType(); NeedAtomicConversion = true; } @@ -5076,6 +5095,9 @@ void InitializationSequence::InitializeFrom(Sema &S, !S.ResolveAddressOfOverloadedFunction(Initializer, DestType, false, dap)) SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + else if (Initializer->getType()->isFunctionType() && + isExprAnUnaddressableFunction(S, Initializer)) + SetFailed(InitializationSequence::FK_AddressOfUnaddressableFunction); else SetFailed(InitializationSequence::FK_ConversionFailed); } else { @@ -6357,7 +6379,7 @@ InitializationSequence::Perform(Sema &S, CastKind = CK_ConstructorConversion; QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); if (S.Context.hasSameUnqualifiedType(SourceType, Class) || - S.IsDerivedFrom(SourceType, Class)) + S.IsDerivedFrom(Loc, SourceType, Class)) IsCopy = true; CreatedObject = true; @@ -6596,6 +6618,8 @@ InitializationSequence::Perform(Sema &S, case SK_CAssignment: { QualType SourceType = CurInit.get()->getType(); + // Save off the initial CurInit in case we need to emit a diagnostic + ExprResult InitialCurInit = CurInit; ExprResult Result = CurInit; Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(Step->Type, Result, true, @@ -6618,7 +6642,7 @@ InitializationSequence::Perform(Sema &S, bool Complained; if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, - CurInit.get(), + InitialCurInit.get(), getAssignmentAction(Entity, true), &Complained)) { PrintInitLocationNote(S, Entity); @@ -6921,6 +6945,13 @@ bool InitializationSequence::Diagnose(Sema &S, break; } + case FK_AddressOfUnaddressableFunction: { + auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(Args[0])->getDecl()); + S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, + Args[0]->getLocStart()); + break; + } + case FK_ReferenceInitOverloadFailed: case FK_UserConversionOverloadFailed: switch (FailedOverloadResult) { @@ -6943,6 +6974,7 @@ bool InitializationSequence::Diagnose(Sema &S, diag::err_typecheck_nonviable_condition_incomplete, Args[0]->getType(), Args[0]->getSourceRange())) S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) + << (Entity.getKind() == InitializedEntity::EK_Result) << Args[0]->getType() << Args[0]->getSourceRange() << DestType.getNonReferenceType(); @@ -7043,10 +7075,12 @@ bool InitializationSequence::Diagnose(Sema &S, SourceRange R; auto *InitList = dyn_cast<InitListExpr>(Args[0]); - if (InitList && InitList->getNumInits() == 1) + if (InitList && InitList->getNumInits() >= 1) { R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd()); - else + } else { + assert(Args.size() > 1 && "Expected multiple initializers!"); R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd()); + } R.setBegin(S.getLocForEndOfToken(R.getBegin())); if (Kind.isCStyleOrFunctionalCast()) @@ -7240,6 +7274,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "array requires initializer list"; break; + case FK_AddressOfUnaddressableFunction: + OS << "address of unaddressable function was taken"; + break; + case FK_ArrayNeedsInitListOrStringLiteral: OS << "array requires initializer list or string literal"; break; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp index 8220641..884add2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp @@ -226,15 +226,16 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { if (LSI->GLTemplateParameterList) return LSI->GLTemplateParameterList; - if (LSI->AutoTemplateParams.size()) { + if (!LSI->AutoTemplateParams.empty()) { SourceRange IntroRange = LSI->IntroducerRange; SourceLocation LAngleLoc = IntroRange.getBegin(); SourceLocation RAngleLoc = IntroRange.getEnd(); LSI->GLTemplateParameterList = TemplateParameterList::Create( SemaRef.Context, /*Template kw loc*/ SourceLocation(), LAngleLoc, - (NamedDecl **)LSI->AutoTemplateParams.data(), - LSI->AutoTemplateParams.size(), RAngleLoc); + llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(), + LSI->AutoTemplateParams.size()), + RAngleLoc); } return LSI->GLTemplateParameterList; } @@ -685,7 +686,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType(); - if (Context.hasSameType(ReturnType, CSI.ReturnType)) + if (Context.getCanonicalFunctionResultType(ReturnType) == + Context.getCanonicalFunctionResultType(CSI.ReturnType)) continue; // FIXME: This is a poor diagnostic for ReturnStmts without expressions. @@ -698,18 +700,11 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { } } -QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, - bool ByRef, - IdentifierInfo *Id, - Expr *&Init) { - - // We do not need to distinguish between direct-list-initialization - // and copy-list-initialization here, because we will always deduce - // std::initializer_list<T>, and direct- and copy-list-initialization - // always behave the same for such a type. - // FIXME: We should model whether an '=' was present. - const bool IsDirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init); - +QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, + bool ByRef, + IdentifierInfo *Id, + bool IsDirectInit, + Expr *&Init) { // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to // deduce against. QualType DeductType = Context.getAutoDeductType(); @@ -722,50 +717,16 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, } TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType); - // Are we a non-list direct initialization? - ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); - - Expr *DeduceInit = Init; - // Initializer could be a C++ direct-initializer. Deduction only works if it - // contains exactly one expression. - if (CXXDirectInit) { - if (CXXDirectInit->getNumExprs() == 0) { - Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_no_expression) - << DeclarationName(Id) << TSI->getType() << Loc; - return QualType(); - } else if (CXXDirectInit->getNumExprs() > 1) { - Diag(CXXDirectInit->getExpr(1)->getLocStart(), - diag::err_init_capture_multiple_expressions) - << DeclarationName(Id) << TSI->getType() << Loc; - return QualType(); - } else { - DeduceInit = CXXDirectInit->getExpr(0); - if (isa<InitListExpr>(DeduceInit)) - Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_paren_braces) - << DeclarationName(Id) << Loc; - } - } - - // Now deduce against the initialization expression and store the deduced - // type below. - QualType DeducedType; - if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) { - if (isa<InitListExpr>(Init)) - Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list) - << DeclarationName(Id) - << (DeduceInit->getType().isNull() ? TSI->getType() - : DeduceInit->getType()) - << DeduceInit->getSourceRange(); - else - Diag(Loc, diag::err_init_capture_deduction_failure) - << DeclarationName(Id) << TSI->getType() - << (DeduceInit->getType().isNull() ? TSI->getType() - : DeduceInit->getType()) - << DeduceInit->getSourceRange(); - } + // Deduce the type of the init capture. + QualType DeducedType = deduceVarTypeFromInitializer( + /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI, + SourceRange(Loc, Loc), IsDirectInit, Init); if (DeducedType.isNull()) return QualType(); + // Are we a non-list direct initialization? + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); + // Perform initialization analysis and ensure any implicit conversions // (such as lvalue-to-rvalue) are enforced. InitializedEntity Entity = @@ -802,9 +763,10 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, return DeducedType; } -VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, - QualType InitCaptureType, IdentifierInfo *Id, Expr *Init) { - +VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, + QualType InitCaptureType, + IdentifierInfo *Id, + unsigned InitStyle, Expr *Init) { TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, Loc); // Create a dummy variable representing the init-capture. This is not actually @@ -815,6 +777,8 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, Loc, Id, InitCaptureType, TSI, SC_Auto); NewVD->setInitCapture(true); NewVD->setReferenced(true); + // FIXME: Pass in a VarDecl::InitializationStyle. + NewVD->setInitStyle(static_cast<VarDecl::InitializationStyle>(InitStyle)); NewVD->markUsed(Context); NewVD->setInit(Init); return NewVD; @@ -1013,8 +977,23 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // in this case. if (C->InitCaptureType.get().isNull()) continue; - Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(), - C->Id, C->Init.get()); + + unsigned InitStyle; + switch (C->InitKind) { + case LambdaCaptureInitKind::NoInit: + llvm_unreachable("not an init-capture?"); + case LambdaCaptureInitKind::CopyInit: + InitStyle = VarDecl::CInit; + break; + case LambdaCaptureInitKind::DirectInit: + InitStyle = VarDecl::CallInit; + break; + case LambdaCaptureInitKind::ListInit: + InitStyle = VarDecl::ListInit; + break; + } + Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(), + C->Id, InitStyle, C->Init.get()); // C++1y [expr.prim.lambda]p11: // An init-capture behaves as if it declares and explicitly // captures a variable [...] whose declarative region is the @@ -1022,6 +1001,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (Var) PushOnScopeChains(Var, CurScope, false); } else { + assert(C->InitKind == LambdaCaptureInitKind::NoInit && + "init capture has valid but null init?"); + // C++11 [expr.prim.lambda]p8: // If a lambda-capture includes a capture-default that is &, the // identifiers in the lambda-capture shall not be preceded by &. @@ -1160,6 +1142,12 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { + // This conversion is explicitly disabled if the lambda's function has + // pass_object_size attributes on any of its parameters. + if (std::any_of(CallOperator->param_begin(), CallOperator->param_end(), + std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>))) + return; + // Add the conversion to function pointer. const FunctionProtoType *CallOpProto = CallOperator->getType()->getAs<FunctionProtoType>(); @@ -1700,8 +1688,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, SC_None); BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false, /*Nested=*/false, /*Copy=*/Init.get()); - Block->setCaptures(Context, &Capture, &Capture + 1, - /*CapturesCXXThis=*/false); + Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false); // Add a fake function body to the block. IR generation is responsible // for filling in the actual body, which cannot be expressed as an AST. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 2e7f891..481ae6c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -11,6 +11,7 @@ // Objective-C++. // //===----------------------------------------------------------------------===// + #include "clang/Sema/Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" @@ -153,7 +154,7 @@ namespace { // by its using directives, transitively) as if they appeared in // the given effective context. void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) { - SmallVector<DeclContext*,4> queue; + SmallVector<DeclContext*, 4> queue; while (true) { for (auto UD : DC->using_directives()) { DeclContext *NS = UD->getNominatedNamespace(); @@ -204,7 +205,7 @@ namespace { UnqualUsingEntry::Comparator())); } }; -} +} // end anonymous namespace // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. @@ -354,13 +355,114 @@ static DeclContext *getContextForScopeMatching(Decl *D) { return D->getDeclContext()->getRedeclContext(); } +/// \brief Determine whether \p D is a better lookup result than \p Existing, +/// given that they declare the same entity. +static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind, + NamedDecl *D, NamedDecl *Existing) { + // When looking up redeclarations of a using declaration, prefer a using + // shadow declaration over any other declaration of the same entity. + if (Kind == Sema::LookupUsingDeclName && isa<UsingShadowDecl>(D) && + !isa<UsingShadowDecl>(Existing)) + return true; + + auto *DUnderlying = D->getUnderlyingDecl(); + auto *EUnderlying = Existing->getUnderlyingDecl(); + + // If they have different underlying declarations, prefer a typedef over the + // original type (this happens when two type declarations denote the same + // type), per a generous reading of C++ [dcl.typedef]p3 and p4. The typedef + // might carry additional semantic information, such as an alignment override. + // However, per C++ [dcl.typedef]p5, when looking up a tag name, prefer a tag + // declaration over a typedef. + if (DUnderlying->getCanonicalDecl() != EUnderlying->getCanonicalDecl()) { + assert(isa<TypeDecl>(DUnderlying) && isa<TypeDecl>(EUnderlying)); + bool HaveTag = isa<TagDecl>(EUnderlying); + bool WantTag = Kind == Sema::LookupTagName; + return HaveTag != WantTag; + } + + // Pick the function with more default arguments. + // FIXME: In the presence of ambiguous default arguments, we should keep both, + // so we can diagnose the ambiguity if the default argument is needed. + // See C++ [over.match.best]p3. + if (auto *DFD = dyn_cast<FunctionDecl>(DUnderlying)) { + auto *EFD = cast<FunctionDecl>(EUnderlying); + unsigned DMin = DFD->getMinRequiredArguments(); + unsigned EMin = EFD->getMinRequiredArguments(); + // If D has more default arguments, it is preferred. + if (DMin != EMin) + return DMin < EMin; + // FIXME: When we track visibility for default function arguments, check + // that we pick the declaration with more visible default arguments. + } + + // Pick the template with more default template arguments. + if (auto *DTD = dyn_cast<TemplateDecl>(DUnderlying)) { + auto *ETD = cast<TemplateDecl>(EUnderlying); + unsigned DMin = DTD->getTemplateParameters()->getMinRequiredArguments(); + unsigned EMin = ETD->getTemplateParameters()->getMinRequiredArguments(); + // If D has more default arguments, it is preferred. Note that default + // arguments (and their visibility) is monotonically increasing across the + // redeclaration chain, so this is a quick proxy for "is more recent". + if (DMin != EMin) + return DMin < EMin; + // If D has more *visible* default arguments, it is preferred. Note, an + // earlier default argument being visible does not imply that a later + // default argument is visible, so we can't just check the first one. + for (unsigned I = DMin, N = DTD->getTemplateParameters()->size(); + I != N; ++I) { + if (!S.hasVisibleDefaultArgument( + ETD->getTemplateParameters()->getParam(I)) && + S.hasVisibleDefaultArgument( + DTD->getTemplateParameters()->getParam(I))) + return true; + } + } + + // For most kinds of declaration, it doesn't really matter which one we pick. + if (!isa<FunctionDecl>(DUnderlying) && !isa<VarDecl>(DUnderlying)) { + // If the existing declaration is hidden, prefer the new one. Otherwise, + // keep what we've got. + return !S.isVisible(Existing); + } + + // Pick the newer declaration; it might have a more precise type. + for (Decl *Prev = DUnderlying->getPreviousDecl(); Prev; + Prev = Prev->getPreviousDecl()) + if (Prev == EUnderlying) + return true; + return false; + + // If the existing declaration is hidden, prefer the new one. Otherwise, + // keep what we've got. + return !S.isVisible(Existing); +} + +/// Determine whether \p D can hide a tag declaration. +static bool canHideTag(NamedDecl *D) { + // C++ [basic.scope.declarative]p4: + // Given a set of declarations in a single declarative region [...] + // exactly one declaration shall declare a class name or enumeration name + // that is not a typedef name and the other declarations shall all refer to + // the same variable or enumerator, or all refer to functions and function + // templates; in this case the class name or enumeration name is hidden. + // C++ [basic.scope.hiding]p2: + // A class name or enumeration name can be hidden by the name of a + // variable, data member, function, or enumerator declared in the same + // scope. + D = D->getUnderlyingDecl(); + return isa<VarDecl>(D) || isa<EnumConstantDecl>(D) || isa<FunctionDecl>(D) || + isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D); +} + /// Resolves the result kind of this lookup. void LookupResult::resolveKind() { unsigned N = Decls.size(); // Fast case: no possible ambiguity. if (N == 0) { - assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation); + assert(ResultKind == NotFound || + ResultKind == NotFoundInCurrentInstantiation); return; } @@ -378,12 +480,15 @@ void LookupResult::resolveKind() { // Don't do any extra resolution if we've already resolved as ambiguous. if (ResultKind == Ambiguous) return; - llvm::SmallPtrSet<NamedDecl*, 16> Unique; - llvm::SmallPtrSet<QualType, 16> UniqueTypes; + llvm::SmallDenseMap<NamedDecl*, unsigned, 16> Unique; + llvm::SmallDenseMap<QualType, unsigned, 16> UniqueTypes; bool Ambiguous = false; - bool HasTag = false, HasFunction = false, HasNonFunction = false; + bool HasTag = false, HasFunction = false; bool HasFunctionTemplate = false, HasUnresolved = false; + NamedDecl *HasNonFunction = nullptr; + + llvm::SmallVector<NamedDecl*, 4> EquivalentNonFunctions; unsigned UniqueTagIndex = 0; @@ -393,34 +498,43 @@ void LookupResult::resolveKind() { D = cast<NamedDecl>(D->getCanonicalDecl()); // Ignore an invalid declaration unless it's the only one left. - if (D->isInvalidDecl() && I < N-1) { + if (D->isInvalidDecl() && !(I == 0 && N == 1)) { Decls[I] = Decls[--N]; continue; } + llvm::Optional<unsigned> ExistingI; + // Redeclarations of types via typedef can occur both within a scope // and, through using declarations and directives, across scopes. There is // no ambiguity if they all refer to the same type, so unique based on the // canonical type. if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { - if (!TD->getDeclContext()->isRecord()) { - QualType T = getSema().Context.getTypeDeclType(TD); - if (!UniqueTypes.insert(getSema().Context.getCanonicalType(T)).second) { - // The type is not unique; pull something off the back and continue - // at this index. - Decls[I] = Decls[--N]; - continue; - } + QualType T = getSema().Context.getTypeDeclType(TD); + auto UniqueResult = UniqueTypes.insert( + std::make_pair(getSema().Context.getCanonicalType(T), I)); + if (!UniqueResult.second) { + // The type is not unique. + ExistingI = UniqueResult.first->second; + } + } + + // For non-type declarations, check for a prior lookup result naming this + // canonical declaration. + if (!ExistingI) { + auto UniqueResult = Unique.insert(std::make_pair(D, I)); + if (!UniqueResult.second) { + // We've seen this entity before. + ExistingI = UniqueResult.first->second; } } - 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). + if (ExistingI) { + // This is not a unique lookup result. Pick one of the results and + // discard the other. + if (isPreferredLookupResult(getSema(), getLookupKind(), Decls[I], + Decls[*ExistingI])) + Decls[*ExistingI] = Decls[I]; Decls[I] = Decls[--N]; continue; } @@ -440,9 +554,21 @@ void LookupResult::resolveKind() { } else if (isa<FunctionDecl>(D)) { HasFunction = true; } else { - if (HasNonFunction) + if (HasNonFunction) { + // If we're about to create an ambiguity between two declarations that + // are equivalent, but one is an internal linkage declaration from one + // module and the other is an internal linkage declaration from another + // module, just skip it. + if (getSema().isEquivalentInternalLinkageDeclaration(HasNonFunction, + D)) { + EquivalentNonFunctions.push_back(D); + Decls[I] = Decls[--N]; + continue; + } + Ambiguous = true; - HasNonFunction = true; + } + HasNonFunction = D; } I++; } @@ -456,15 +582,24 @@ void LookupResult::resolveKind() { // wherever the object, function, or enumerator name is visible. // But it's still an error if there are distinct tag types found, // even if they're not visible. (ref?) - if (HideTags && HasTag && !Ambiguous && + if (N > 1 && HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction || HasUnresolved)) { - if (getContextForScopeMatching(Decls[UniqueTagIndex])->Equals( - getContextForScopeMatching(Decls[UniqueTagIndex ? 0 : N - 1]))) + NamedDecl *OtherDecl = Decls[UniqueTagIndex ? 0 : N - 1]; + if (isa<TagDecl>(Decls[UniqueTagIndex]->getUnderlyingDecl()) && + getContextForScopeMatching(Decls[UniqueTagIndex])->Equals( + getContextForScopeMatching(OtherDecl)) && + canHideTag(OtherDecl)) Decls[UniqueTagIndex] = Decls[--N]; else Ambiguous = true; } + // FIXME: This diagnostic should really be delayed until we're done with + // the lookup result, in case the ambiguity is resolved by the caller. + if (!EquivalentNonFunctions.empty() && !Ambiguous) + getSema().diagnoseEquivalentInternalLinkageDeclarations( + getNameLoc(), HasNonFunction, EquivalentNonFunctions); + Decls.set_size(N); if (HasNonFunction && (HasFunction || HasUnresolved)) @@ -534,6 +669,11 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) { R.addDecl(S.getASTContext().getFloat128StubType()); return true; } + if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName && + II == S.getASTContext().getMakeIntegerSeqName()) { + R.addDecl(S.getASTContext().getMakeIntegerSeqDecl()); + return true; + } // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) { @@ -875,7 +1015,7 @@ struct FindLocalExternScope { LookupResult &R; bool OldFindLocalExtern; }; -} +} // end anonymous namespace bool Sema::CppLookupName(LookupResult &R, Scope *S) { assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); @@ -1333,22 +1473,22 @@ bool Sema::hasVisibleDefaultArgument(const NamedDecl *D, /// your module can see, including those later on in your module). bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { 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)) + Module *DeclModule = nullptr; + + if (SemaRef.getLangOpts().ModulesLocalVisibility) { + 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; - // Also check merged definitions. - if (SemaRef.getLangOpts().ModulesLocalVisibility && - SemaRef.hasVisibleMergedDefinition(D)) + } + + // 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()) && + (SemaRef.isModuleVisible(DeclModule) || + SemaRef.hasVisibleMergedDefinition(D))) return true; } @@ -1380,6 +1520,11 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { if (LookupModules.empty()) return false; + if (!DeclModule) { + DeclModule = SemaRef.getOwningModule(D); + assert(DeclModule && "hidden decl not from a module"); + } + // If our lookup set contains the decl's module, it's visible. if (LookupModules.count(DeclModule)) return true; @@ -1390,18 +1535,22 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { // Check whether DeclModule is transitively exported to an import of // the lookup set. - for (llvm::DenseSet<Module *>::iterator I = LookupModules.begin(), - E = LookupModules.end(); - I != E; ++I) - if ((*I)->isModuleVisible(DeclModule)) - return true; - return false; + return std::any_of(LookupModules.begin(), LookupModules.end(), + [&](Module *M) { return M->isModuleVisible(DeclModule); }); } bool Sema::isVisibleSlow(const NamedDecl *D) { return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D)); } +bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) { + for (auto *D : R) { + if (isVisible(D)) + return true; + } + return New->isExternallyVisible(); +} + /// \brief Retrieve the visible declaration corresponding to D, if any. /// /// This routine determines whether the declaration D is visible in the current @@ -1679,12 +1828,10 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, /// \brief Callback that looks for any member of a class with the given name. static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - void *Name) { + CXXBasePath &Path, DeclarationName Name) { RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); - DeclarationName N = DeclarationName::getFromOpaquePtr(Name); - Path.Decls = BaseRecord->lookup(N); + Path.Decls = BaseRecord->lookup(Name); return !Path.Decls.empty(); } @@ -1756,7 +1903,18 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, cast<TagDecl>(LookupCtx)->isBeingDefined()) && "Declaration context must already be complete!"); - // Perform qualified name lookup into the LookupCtx. + struct QualifiedLookupInScope { + bool oldVal; + DeclContext *Context; + // Set flag in DeclContext informing debugger that we're looking for qualified name + QualifiedLookupInScope(DeclContext *ctx) : Context(ctx) { + oldVal = ctx->setUseQualifiedLookup(); + } + ~QualifiedLookupInScope() { + Context->setUseQualifiedLookup(oldVal); + } + } QL(LookupCtx); + if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (isa<CXXRecordDecl>(LookupCtx)) @@ -1802,7 +1960,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, Paths.setOrigin(LookupRec); // Look for this member in our base classes - CXXRecordDecl::BaseMatchesCallback *BaseCallback = nullptr; + bool (*BaseCallback)(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, + DeclarationName Name) = nullptr; switch (R.getLookupKind()) { case LookupObjCImplicitSelfParam: case LookupOrdinaryName: @@ -1835,8 +1994,12 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, break; } - if (!LookupRec->lookupInBases(BaseCallback, - R.getLookupName().getAsOpaquePtr(), Paths)) + DeclarationName Name = R.getLookupName(); + if (!LookupRec->lookupInBases( + [=](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + return BaseCallback(Specifier, Path, Name); + }, + Paths)) return false; R.setNamingClass(LookupRec); @@ -2013,17 +2176,30 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, /// /// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) { + // The access-control rules we use here are essentially the rules for + // doing a lookup in Class that just magically skipped the direct + // members of Class itself. That is, the naming class is Class, and the + // access includes the access of the base. for (const auto &BaseSpec : Class->bases()) { CXXRecordDecl *RD = cast<CXXRecordDecl>( BaseSpec.getType()->castAs<RecordType>()->getDecl()); LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind()); Result.setBaseObjectType(Context.getRecordType(Class)); LookupQualifiedName(Result, RD); - for (auto *Decl : Result) - R.addDecl(Decl); + + // Copy the lookup results into the target, merging the base's access into + // the path access. + for (auto I = Result.begin(), E = Result.end(); I != E; ++I) { + R.addDecl(I.getDecl(), + CXXRecordDecl::MergeAccess(BaseSpec.getAccessSpecifier(), + I.getAccess())); + } + + Result.suppressDiagnostics(); } R.resolveKind(); + R.setNamingClass(Class); return !R.empty(); } @@ -2075,7 +2251,7 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { case LookupResult::AmbiguousTagHiding: { Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange; - llvm::SmallPtrSet<NamedDecl*,8> TagDecls; + llvm::SmallPtrSet<NamedDecl*, 8> TagDecls; for (auto *D : Result) if (TagDecl *TD = dyn_cast<TagDecl>(D)) { @@ -2121,7 +2297,7 @@ namespace { Sema::AssociatedClassSet &Classes; SourceLocation InstantiationLoc; }; -} +} // end anonymous namespace static void addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T); @@ -2252,7 +2428,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, } // Only recurse into base classes for complete types. - if (!Class->hasDefinition()) + if (!Result.S.isCompleteType(Result.InstantiationLoc, + Result.S.Context.getRecordType(Class))) return; // Add direct and indirect base classes along with their associated @@ -2345,10 +2522,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { // classes. Its associated namespaces are the namespaces in // which its associated classes are defined. case Type::Record: { - Result.S.RequireCompleteType(Result.InstantiationLoc, QualType(T, 0), - /*no diagnostic*/ 0); - CXXRecordDecl *Class - = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl()); + CXXRecordDecl *Class = + cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl()); addAssociatedClassesAndNamespaces(Result, Class); break; } @@ -3032,7 +3207,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) { DeclContext *LexDC = DI->getLexicalDeclContext(); if (isa<CXXRecordDecl>(LexDC) && - AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) { + AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)) && + isVisible(cast<NamedDecl>(DI))) { DeclaredInAssociatedClass = true; break; } @@ -3129,9 +3305,6 @@ public: } // end anonymous namespace NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) { - // Look through using declarations. - ND = ND->getUnderlyingDecl(); - unsigned IDNS = ND->getIdentifierNamespace(); std::list<ShadowMap>::reverse_iterator SM = ShadowMaps.rbegin(); for (std::list<ShadowMap>::reverse_iterator SMEnd = ShadowMaps.rend(); @@ -3704,7 +3877,12 @@ void TypoCorrectionConsumer::addNamespaces( if (const Type *T = NNS->getAsType()) SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization; } - for (const auto *TI : SemaRef.getASTContext().types()) { + // Do not transform this into an iterator-based loop. The loop body can + // trigger the creation of further types (through lazy deserialization) and + // invalide iterators into this list. + auto &Types = SemaRef.getASTContext().getTypes(); + for (unsigned I = 0; I != Types.size(); ++I) { + const auto *TI = Types[I]; if (CXXRecordDecl *CD = TI->getAsCXXRecordDecl()) { CD = CD->getCanonicalDecl(); if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() && @@ -3805,7 +3983,8 @@ void TypoCorrectionConsumer::performQualifiedLookups() { // current correction candidate is the name of that class, then skip // it as it is unlikely a qualified version of the class' constructor // is an appropriate correction. - if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() : 0) { + if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() : + nullptr) { if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo()) continue; } @@ -4540,7 +4719,7 @@ void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) { if (isKeyword()) CorrectionDecls.clear(); - CorrectionDecls.push_back(CDecl->getUnderlyingDecl()); + CorrectionDecls.push_back(CDecl); if (!CorrectionName) CorrectionName = CDecl->getDeclName(); @@ -4769,7 +4948,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, // Maybe we're just missing a module import. if (Correction.requiresImport()) { - NamedDecl *Decl = Correction.getCorrectionDecl(); + NamedDecl *Decl = Correction.getFoundDecl(); assert(Decl && "import required but no declaration to import"); diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl, @@ -4781,7 +4960,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, << CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint()); NamedDecl *ChosenDecl = - Correction.isKeyword() ? nullptr : Correction.getCorrectionDecl(); + Correction.isKeyword() ? nullptr : Correction.getFoundDecl(); if (PrevNote.getDiagID() && ChosenDecl) Diag(ChosenDecl->getLocation(), PrevNote) << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp index f139c83..1cb84e4 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -61,8 +61,10 @@ static Qualifiers::ObjCLifetime getImpliedARCOwnership( return Qualifiers::OCL_None; } -/// Check the internal consistency of a property declaration. -static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) { +/// Check the internal consistency of a property declaration with +/// an explicit ownership qualifier. +static void checkPropertyDeclWithOwnership(Sema &S, + ObjCPropertyDecl *property) { if (property->isInvalidDecl()) return; ObjCPropertyDecl::PropertyAttributeKind propertyKind @@ -70,8 +72,7 @@ static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) { Qualifiers::ObjCLifetime propertyLifetime = property->getType().getObjCLifetime(); - // Nothing to do if we don't have a lifetime. - if (propertyLifetime == Qualifiers::OCL_None) return; + assert(propertyLifetime != Qualifiers::OCL_None); Qualifiers::ObjCLifetime expectedLifetime = getImpliedARCOwnership(propertyKind, property->getType()); @@ -127,32 +128,71 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, CheckPropertyAgainstProtocol(S, Prop, P, Known); } +static unsigned deducePropertyOwnershipFromType(Sema &S, QualType T) { + // In GC mode, just look for the __weak qualifier. + if (S.getLangOpts().getGC() != LangOptions::NonGC) { + if (T.isObjCGCWeak()) return ObjCDeclSpec::DQ_PR_weak; + + // In ARC/MRC, look for an explicit ownership qualifier. + // For some reason, this only applies to __weak. + } else if (auto ownership = T.getObjCLifetime()) { + switch (ownership) { + case Qualifiers::OCL_Weak: + return ObjCDeclSpec::DQ_PR_weak; + case Qualifiers::OCL_Strong: + return ObjCDeclSpec::DQ_PR_strong; + case Qualifiers::OCL_ExplicitNone: + return ObjCDeclSpec::DQ_PR_unsafe_unretained; + case Qualifiers::OCL_Autoreleasing: + case Qualifiers::OCL_None: + return 0; + } + llvm_unreachable("bad qualifier"); + } + + return 0; +} + +static const unsigned OwnershipMask = + (ObjCPropertyDecl::OBJC_PR_assign | + ObjCPropertyDecl::OBJC_PR_retain | + ObjCPropertyDecl::OBJC_PR_copy | + ObjCPropertyDecl::OBJC_PR_weak | + ObjCPropertyDecl::OBJC_PR_strong | + ObjCPropertyDecl::OBJC_PR_unsafe_unretained); + +static unsigned getOwnershipRule(unsigned attr) { + unsigned result = attr & OwnershipMask; + + // From an ownership perspective, assign and unsafe_unretained are + // identical; make sure one also implies the other. + if (result & (ObjCPropertyDecl::OBJC_PR_assign | + ObjCPropertyDecl::OBJC_PR_unsafe_unretained)) { + result |= ObjCPropertyDecl::OBJC_PR_assign | + ObjCPropertyDecl::OBJC_PR_unsafe_unretained; + } + + return result; +} + Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, FieldDeclarator &FD, ObjCDeclSpec &ODS, Selector GetterSel, Selector SetterSel, - bool *isOverridingProperty, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC) { unsigned Attributes = ODS.getPropertyAttributes(); FD.D.setObjCWeakProperty((Attributes & ObjCDeclSpec::DQ_PR_weak) != 0); TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); QualType T = TSI->getType(); - Attributes |= deduceWeakPropertyFromType(T); + if (!getOwnershipRule(Attributes)) { + Attributes |= deducePropertyOwnershipFromType(*this, T); + } bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || // default is readwrite! !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); - // property is defaulted to 'assign' if it is readwrite and is - // not retain or copy - bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || - (isReadWrite && - !(Attributes & ObjCDeclSpec::DQ_PR_retain) && - !(Attributes & ObjCDeclSpec::DQ_PR_strong) && - !(Attributes & ObjCDeclSpec::DQ_PR_copy) && - !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) && - !(Attributes & ObjCDeclSpec::DQ_PR_weak))); // Proceed with constructing the ObjCPropertyDecls. ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext); @@ -161,11 +201,10 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, if (CDecl->IsClassExtension()) { Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc, FD, GetterSel, SetterSel, - isAssign, isReadWrite, + isReadWrite, Attributes, ODS.getPropertyAttributes(), - isOverridingProperty, T, TSI, - MethodImplKind); + T, TSI, MethodImplKind); if (!Res) return nullptr; } @@ -173,7 +212,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, if (!Res) { Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD, - GetterSel, SetterSel, isAssign, isReadWrite, + GetterSel, SetterSel, isReadWrite, Attributes, ODS.getPropertyAttributes(), T, TSI, MethodImplKind); if (lexicalDC) @@ -181,12 +220,13 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, } // Validate the attributes on the @property. - CheckObjCPropertyAttributes(Res, AtLoc, Attributes, + CheckObjCPropertyAttributes(Res, AtLoc, Attributes, (isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCProtocolDecl>(ClassDecl))); - if (getLangOpts().ObjCAutoRefCount) - checkARCPropertyDecl(*this, Res); + // Check consistency if the type has explicit ownership qualification. + if (Res->getType().getObjCLifetime()) + checkPropertyDeclWithOwnership(*this, Res); llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos; if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { @@ -220,8 +260,12 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, } } } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { - for (auto *P : Cat->protocols()) - CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); + // We don't check if class extension. Because properties in class extension + // are meant to override some of the attributes and checking has already done + // when property in class extension is constructed. + if (!Cat->IsClassExtension()) + for (auto *P : Cat->protocols()) + CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); } else { ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl); for (auto *P : Proto->protocols()) @@ -293,13 +337,73 @@ static bool LocPropertyAttribute( ASTContext &Context, const char *attrName, } -static unsigned getOwnershipRule(unsigned attr) { - return attr & (ObjCPropertyDecl::OBJC_PR_assign | - ObjCPropertyDecl::OBJC_PR_retain | - ObjCPropertyDecl::OBJC_PR_copy | - ObjCPropertyDecl::OBJC_PR_weak | - ObjCPropertyDecl::OBJC_PR_strong | - ObjCPropertyDecl::OBJC_PR_unsafe_unretained); +/// Check for a mismatch in the atomicity of the given properties. +static void checkAtomicPropertyMismatch(Sema &S, + ObjCPropertyDecl *OldProperty, + ObjCPropertyDecl *NewProperty, + bool PropagateAtomicity) { + // If the atomicity of both matches, we're done. + bool OldIsAtomic = + (OldProperty->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic) + == 0; + bool NewIsAtomic = + (NewProperty->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic) + == 0; + if (OldIsAtomic == NewIsAtomic) return; + + // Determine whether the given property is readonly and implicitly + // atomic. + auto isImplicitlyReadonlyAtomic = [](ObjCPropertyDecl *Property) -> bool { + // Is it readonly? + auto Attrs = Property->getPropertyAttributes(); + if ((Attrs & ObjCPropertyDecl::OBJC_PR_readonly) == 0) return false; + + // Is it nonatomic? + if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) return false; + + // Was 'atomic' specified directly? + if (Property->getPropertyAttributesAsWritten() & + ObjCPropertyDecl::OBJC_PR_atomic) + return false; + + return true; + }; + + // If we're allowed to propagate atomicity, and the new property did + // not specify atomicity at all, propagate. + const unsigned AtomicityMask = + (ObjCPropertyDecl::OBJC_PR_atomic | ObjCPropertyDecl::OBJC_PR_nonatomic); + if (PropagateAtomicity && + ((NewProperty->getPropertyAttributesAsWritten() & AtomicityMask) == 0)) { + unsigned Attrs = NewProperty->getPropertyAttributes(); + Attrs = Attrs & ~AtomicityMask; + if (OldIsAtomic) + Attrs |= ObjCPropertyDecl::OBJC_PR_atomic; + else + Attrs |= ObjCPropertyDecl::OBJC_PR_nonatomic; + + NewProperty->overwritePropertyAttributes(Attrs); + return; + } + + // One of the properties is atomic; if it's a readonly property, and + // 'atomic' wasn't explicitly specified, we're okay. + if ((OldIsAtomic && isImplicitlyReadonlyAtomic(OldProperty)) || + (NewIsAtomic && isImplicitlyReadonlyAtomic(NewProperty))) + return; + + // Diagnose the conflict. + const IdentifierInfo *OldContextName; + auto *OldDC = OldProperty->getDeclContext(); + if (auto Category = dyn_cast<ObjCCategoryDecl>(OldDC)) + OldContextName = Category->getClassInterface()->getIdentifier(); + else + OldContextName = cast<ObjCContainerDecl>(OldDC)->getIdentifier(); + + S.Diag(NewProperty->getLocation(), diag::warn_property_attribute) + << NewProperty->getDeclName() << "atomic" + << OldContextName; + S.Diag(OldProperty->getLocation(), diag::note_property_declare); } ObjCPropertyDecl * @@ -308,11 +412,9 @@ Sema::HandlePropertyInClassExtension(Scope *S, SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, Selector SetterSel, - const bool isAssign, const bool isReadWrite, - const unsigned Attributes, + unsigned &Attributes, const unsigned AttributesAsWritten, - bool *isOverridingProperty, QualType T, TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind) { @@ -322,80 +424,102 @@ Sema::HandlePropertyInClassExtension(Scope *S, IdentifierInfo *PropertyId = FD.D.getIdentifier(); ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); - if (CCPrimary) { - // Check for duplicate declaration of this property in current and - // other class extensions. - for (const auto *Ext : CCPrimary->known_extensions()) { - if (ObjCPropertyDecl *prevDecl - = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) { - Diag(AtLoc, diag::err_duplicate_property); - Diag(prevDecl->getLocation(), diag::note_property_declare); - return nullptr; - } - } - } - - // Create a new ObjCPropertyDecl with the DeclContext being - // the class extension. - // FIXME. We should really be using CreatePropertyDecl for this. - ObjCPropertyDecl *PDecl = - ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), - PropertyId, AtLoc, LParenLoc, T, TSI); - PDecl->setPropertyAttributesAsWritten( - makePropertyAttributesAsWritten(AttributesAsWritten)); - if (Attributes & ObjCDeclSpec::DQ_PR_readonly) - PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); - if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) - PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); - if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) - PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); - if (Attributes & ObjCDeclSpec::DQ_PR_atomic) - PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); - if (Attributes & ObjCDeclSpec::DQ_PR_nullability) - PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability); - if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable) - PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable); - - // Set setter/getter selector name. Needed later. - PDecl->setGetterName(GetterSel); - PDecl->setSetterName(SetterSel); - ProcessDeclAttributes(S, PDecl, FD.D); - DC->addDecl(PDecl); - // We need to look in the @interface to see if the @property was // already declared. if (!CCPrimary) { Diag(CDecl->getLocation(), diag::err_continuation_class); - *isOverridingProperty = true; return nullptr; } - // Find the property in continuation class's primary class only. + // Find the property in the extended class's primary class or + // extensions. ObjCPropertyDecl *PIDecl = CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); + // If we found a property in an extension, complain. + if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) { + Diag(AtLoc, diag::err_duplicate_property); + Diag(PIDecl->getLocation(), diag::note_property_declare); + return nullptr; + } + + // Check for consistency with the previous declaration, if there is one. + if (PIDecl) { + // A readonly property declared in the primary class can be refined + // by adding a readwrite property within an extension. + // Anything else is an error. + if (!(PIDecl->isReadOnly() && isReadWrite)) { + // Tailor the diagnostics for the common case where a readwrite + // property is declared both in the @interface and the continuation. + // This is a common error where the user often intended the original + // declaration to be readonly. + unsigned diag = + (Attributes & ObjCDeclSpec::DQ_PR_readwrite) && + (PIDecl->getPropertyAttributesAsWritten() & + ObjCPropertyDecl::OBJC_PR_readwrite) + ? diag::err_use_continuation_class_redeclaration_readwrite + : diag::err_use_continuation_class; + Diag(AtLoc, diag) + << CCPrimary->getDeclName(); + Diag(PIDecl->getLocation(), diag::note_property_declare); + return nullptr; + } + + // Check for consistency of getters. + if (PIDecl->getGetterName() != GetterSel) { + // If the getter was written explicitly, complain. + if (AttributesAsWritten & ObjCDeclSpec::DQ_PR_getter) { + Diag(AtLoc, diag::warn_property_redecl_getter_mismatch) + << PIDecl->getGetterName() << GetterSel; + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + + // Always adopt the getter from the original declaration. + GetterSel = PIDecl->getGetterName(); + Attributes |= ObjCDeclSpec::DQ_PR_getter; + } + + // Check consistency of ownership. + unsigned ExistingOwnership + = getOwnershipRule(PIDecl->getPropertyAttributes()); + unsigned NewOwnership = getOwnershipRule(Attributes); + if (ExistingOwnership && NewOwnership != ExistingOwnership) { + // If the ownership was written explicitly, complain. + if (getOwnershipRule(AttributesAsWritten)) { + Diag(AtLoc, diag::warn_property_attr_mismatch); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + + // Take the ownership from the original property. + Attributes = (Attributes & ~OwnershipMask) | ExistingOwnership; + } + + // If the redeclaration is 'weak' but the original property is not, + if ((Attributes & ObjCPropertyDecl::OBJC_PR_weak) && + !(PIDecl->getPropertyAttributesAsWritten() + & ObjCPropertyDecl::OBJC_PR_weak) && + PIDecl->getType()->getAs<ObjCObjectPointerType>() && + PIDecl->getType().getObjCLifetime() == Qualifiers::OCL_None) { + Diag(AtLoc, diag::warn_property_implicitly_mismatched); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + } + + // Create a new ObjCPropertyDecl with the DeclContext being + // the class extension. + ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc, + FD, GetterSel, SetterSel, + isReadWrite, + Attributes, AttributesAsWritten, + T, TSI, MethodImplKind, DC); + + // If there was no declaration of a property with the same name in + // the primary class, we're done. if (!PIDecl) { - // No matching property found in the primary class. Just fall thru - // and add property to continuation class's primary class. - ObjCPropertyDecl *PrimaryPDecl = - CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc, - FD, GetterSel, SetterSel, isAssign, isReadWrite, - Attributes,AttributesAsWritten, T, TSI, MethodImplKind, - DC); - - // A case of continuation class adding a new property in the class. This - // is not what it was meant for. However, gcc supports it and so should we. - // Make sure setter/getters are declared here. - ProcessPropertyDecl(PrimaryPDecl, CCPrimary, - /* redeclaredProperty = */ nullptr, - /* lexicalDC = */ CDecl); - PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl()); - PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl()); - if (ASTMutationListener *L = Context.getASTMutationListener()) - L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr, - CDecl); - return PrimaryPDecl; + ProcessPropertyDecl(PDecl); + return PDecl; } + if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) { bool IncompatibleObjC = false; QualType ConvertedType; @@ -418,103 +542,13 @@ Sema::HandlePropertyInClassExtension(Scope *S, return nullptr; } } - - // The property 'PIDecl's readonly attribute will be over-ridden - // with continuation class's readwrite property attribute! - unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); - if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { - PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly; - PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite; - PIkind |= deduceWeakPropertyFromType(PIDecl->getType()); - unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes); - unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind); - if (PrimaryClassMemoryModel && ClassExtensionMemoryModel && - (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) { - Diag(AtLoc, diag::warn_property_attr_mismatch); - Diag(PIDecl->getLocation(), diag::note_property_declare); - } - else if (getLangOpts().ObjCAutoRefCount) { - QualType PrimaryPropertyQT = - Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType(); - if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) { - bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0); - Qualifiers::ObjCLifetime PrimaryPropertyLifeTime = - PrimaryPropertyQT.getObjCLifetime(); - if (PrimaryPropertyLifeTime == Qualifiers::OCL_None && - (Attributes & ObjCDeclSpec::DQ_PR_weak) && - !PropertyIsWeak) { - Diag(AtLoc, diag::warn_property_implicitly_mismatched); - Diag(PIDecl->getLocation(), diag::note_property_declare); - } - } - } - - DeclContext *DC = cast<DeclContext>(CCPrimary); - if (!ObjCPropertyDecl::findPropertyDecl(DC, - PIDecl->getDeclName().getAsIdentifierInfo())) { - // In mrr mode, 'readwrite' property must have an explicit - // memory attribute. If none specified, select the default (assign). - if (!getLangOpts().ObjCAutoRefCount) { - if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign | - ObjCDeclSpec::DQ_PR_retain | - ObjCDeclSpec::DQ_PR_strong | - ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_unsafe_unretained | - ObjCDeclSpec::DQ_PR_weak))) - PIkind |= ObjCPropertyDecl::OBJC_PR_assign; - } - - // Protocol is not in the primary class. Must build one for it. - ObjCDeclSpec ProtocolPropertyODS; - // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind - // and ObjCPropertyDecl::PropertyAttributeKind have identical - // values. Should consolidate both into one enum type. - ProtocolPropertyODS. - setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) - PIkind); - // Must re-establish the context from class extension to primary - // class context. - ContextRAII SavedContext(*this, CCPrimary); - - Decl *ProtocolPtrTy = - ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS, - PIDecl->getGetterName(), - PIDecl->getSetterName(), - isOverridingProperty, - MethodImplKind, - /* lexicalDC = */ CDecl); - PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy); - } - PIDecl->makeitReadWriteAttribute(); - if (Attributes & ObjCDeclSpec::DQ_PR_retain) - PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); - if (Attributes & ObjCDeclSpec::DQ_PR_strong) - PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); - if (Attributes & ObjCDeclSpec::DQ_PR_copy) - PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); - PIDecl->setSetterName(SetterSel); - } else { - // Tailor the diagnostics for the common case where a readwrite - // property is declared both in the @interface and the continuation. - // This is a common error where the user often intended the original - // declaration to be readonly. - unsigned diag = - (Attributes & ObjCDeclSpec::DQ_PR_readwrite) && - (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) - ? diag::err_use_continuation_class_redeclaration_readwrite - : diag::err_use_continuation_class; - Diag(AtLoc, diag) - << CCPrimary->getDeclName(); - Diag(PIDecl->getLocation(), diag::note_property_declare); - return nullptr; - } - *isOverridingProperty = true; - // Make sure setter decl is synthesized, and added to primary class's list. - ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl); - PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl()); - PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl()); - if (ASTMutationListener *L = Context.getASTMutationListener()) - L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl); + + // Check that atomicity of property in class extension matches the previous + // declaration. + checkAtomicPropertyMismatch(*this, PIDecl, PDecl, true); + + // Make sure getter/setter are appropriately synthesized. + ProcessPropertyDecl(PDecl); return PDecl; } @@ -525,7 +559,6 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, FieldDeclarator &FD, Selector GetterSel, Selector SetterSel, - const bool isAssign, const bool isReadWrite, const unsigned Attributes, const unsigned AttributesAsWritten, @@ -535,10 +568,23 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, DeclContext *lexicalDC){ IdentifierInfo *PropertyId = FD.D.getIdentifier(); - // Issue a warning if property is 'assign' as default and its object, which is - // gc'able conforms to NSCopying protocol + // Property defaults to 'assign' if it is readwrite, unless this is ARC + // and the type is retainable. + bool isAssign; + if (Attributes & (ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_unsafe_unretained)) { + isAssign = true; + } else if (getOwnershipRule(Attributes) || !isReadWrite) { + isAssign = false; + } else { + isAssign = (!getLangOpts().ObjCAutoRefCount || + !T->isObjCRetainableType()); + } + + // Issue a warning if property is 'assign' as default and its + // object, which is gc'able conforms to NSCopying protocol if (getLangOpts().getGC() != LangOptions::NonGC && - isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) + isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) { if (const ObjCObjectPointerType *ObjPtrTy = T->getAs<ObjCObjectPointerType>()) { ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); @@ -548,6 +594,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, if (IDecl->ClassImplementsProtocol(PNSCopying, true)) Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; } + } if (T->isObjCObjectType()) { SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd(); @@ -663,8 +710,10 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, // We're fine if they match. if (propertyLifetime == ivarLifetime) return; - // These aren't valid lifetimes for object ivars; don't diagnose twice. - if (ivarLifetime == Qualifiers::OCL_None || + // None isn't a valid lifetime for an object ivar in ARC, and + // __autoreleasing is never valid; don't diagnose twice. + if ((ivarLifetime == Qualifiers::OCL_None && + S.getLangOpts().ObjCAutoRefCount) || ivarLifetime == Qualifiers::OCL_Autoreleasing) return; @@ -797,6 +846,38 @@ DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc, S.Diag(AtLoc, diag::note_property_synthesize); } +/// Determine whether any storage attributes were written on the property. +static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop) { + if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true; + + // If this is a readwrite property in a class extension that refines + // a readonly property in the original class definition, check it as + // well. + + // If it's a readonly property, we're not interested. + if (Prop->isReadOnly()) return false; + + // Is it declared in an extension? + auto Category = dyn_cast<ObjCCategoryDecl>(Prop->getDeclContext()); + if (!Category || !Category->IsClassExtension()) return false; + + // Find the corresponding property in the primary class definition. + auto OrigClass = Category->getClassInterface(); + for (auto Found : OrigClass->lookup(Prop->getDeclName())) { + if (ObjCPropertyDecl *OrigProp = dyn_cast<ObjCPropertyDecl>(Found)) + return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask; + } + + // Look through all of the protocols. + for (const auto *Proto : OrigClass->all_referenced_protocols()) { + if (ObjCPropertyDecl *OrigProp = + Proto->FindPropertyDeclaration(Prop->getIdentifier())) + return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask; + } + + return false; +} + /// ActOnPropertyImplDecl - This routine performs semantic checks and /// builds the AST node for a property implementation declaration; declared /// as \@synthesize or \@dynamic. @@ -953,18 +1034,49 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, ObjCPropertyDecl::PropertyAttributeKind kind = property->getPropertyAttributes(); - // Add GC __weak to the ivar type if the property is weak. - if ((kind & ObjCPropertyDecl::OBJC_PR_weak) && - getLangOpts().getGC() != LangOptions::NonGC) { - assert(!getLangOpts().ObjCAutoRefCount); - if (PropertyIvarType.isObjCGCStrong()) { - Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type); - Diag(property->getLocation(), diag::note_property_declare); + bool isARCWeak = false; + if (kind & ObjCPropertyDecl::OBJC_PR_weak) { + // Add GC __weak to the ivar type if the property is weak. + if (getLangOpts().getGC() != LangOptions::NonGC) { + assert(!getLangOpts().ObjCAutoRefCount); + if (PropertyIvarType.isObjCGCStrong()) { + Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type); + Diag(property->getLocation(), diag::note_property_declare); + } else { + PropertyIvarType = + Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak); + } + + // Otherwise, check whether ARC __weak is enabled and works with + // the property type. } else { - PropertyIvarType = - Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak); + if (!getLangOpts().ObjCWeak) { + // Only complain here when synthesizing an ivar. + if (!Ivar) { + Diag(PropertyDiagLoc, + getLangOpts().ObjCWeakRuntime + ? diag::err_synthesizing_arc_weak_property_disabled + : diag::err_synthesizing_arc_weak_property_no_runtime); + Diag(property->getLocation(), diag::note_property_declare); + } + CompleteTypeErr = true; // suppress later diagnostics about the ivar + } else { + isARCWeak = true; + if (const ObjCObjectPointerType *ObjT = + PropertyIvarType->getAs<ObjCObjectPointerType>()) { + const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl(); + if (ObjI && ObjI->isArcWeakrefUnavailable()) { + Diag(property->getLocation(), + diag::err_arc_weak_unavailable_property) + << PropertyIvarType; + Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class) + << ClassImpDecl->getName(); + } + } + } } } + if (AtLoc.isInvalid()) { // Check when default synthesizing a property that there is // an ivar matching property name and issue warning; since this @@ -987,13 +1099,13 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (!Ivar) { // In ARC, give the ivar a lifetime qualifier based on the // property attributes. - if (getLangOpts().ObjCAutoRefCount && + if ((getLangOpts().ObjCAutoRefCount || isARCWeak) && !PropertyIvarType.getObjCLifetime() && PropertyIvarType->isObjCRetainableType()) { // It's an error if we have to do this and the user didn't // explicitly write an ownership attribute on the property. - if (!property->hasWrittenStorageAttribute() && + if (!hasWrittenStorageAttribute(property) && !(kind & ObjCPropertyDecl::OBJC_PR_strong)) { Diag(PropertyDiagLoc, diag::err_arc_objc_property_default_assign_on_object); @@ -1002,24 +1114,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Qualifiers::ObjCLifetime lifetime = getImpliedARCOwnership(kind, PropertyIvarType); assert(lifetime && "no lifetime for property?"); - if (lifetime == Qualifiers::OCL_Weak) { - bool err = false; - if (const ObjCObjectPointerType *ObjT = - PropertyIvarType->getAs<ObjCObjectPointerType>()) { - const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl(); - if (ObjI && ObjI->isArcWeakrefUnavailable()) { - Diag(property->getLocation(), - diag::err_arc_weak_unavailable_property) << PropertyIvarType; - Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class) - << ClassImpDecl->getName(); - err = true; - } - } - if (!err && !getLangOpts().ObjCARCWeak) { - Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime); - Diag(property->getLocation(), diag::note_property_declare); - } - } Qualifiers qs; qs.addObjCLifetime(lifetime); @@ -1027,13 +1121,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } } - if (kind & ObjCPropertyDecl::OBJC_PR_weak && - !getLangOpts().ObjCAutoRefCount && - getLangOpts().getGC() == LangOptions::NonGC) { - Diag(PropertyDiagLoc, diag::error_synthesize_weak_non_arc_or_gc); - Diag(property->getLocation(), diag::note_property_declare); - } - Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyIvarLoc,PropertyIvarLoc, PropertyIvar, PropertyIvarType, /*Dinfo=*/nullptr, @@ -1121,7 +1208,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // Fall thru - see previous comment } } - if (getLangOpts().ObjCAutoRefCount) + if (getLangOpts().ObjCAutoRefCount || isARCWeak || + Ivar->getType().getObjCLifetime()) checkARCPropertyImpl(*this, PropertyLoc, property, Ivar); } else if (PropertyIvar) // @dynamic @@ -1349,12 +1437,10 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, } } - if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) - != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) { - Diag(Property->getLocation(), diag::warn_property_attribute) - << Property->getDeclName() << "atomic" << inheritedName; - Diag(SuperProperty->getLocation(), diag::note_property_declare); - } + // Check for nonatomic; note that nonatomic is effectively + // meaningless for readonly properties, so don't diagnose if the + // atomic property is 'readonly'. + checkAtomicPropertyMismatch(*this, SuperProperty, Property, false); if (Property->getSetterName() != SuperProperty->getSetterName()) { Diag(Property->getLocation(), diag::warn_property_attribute) << Property->getDeclName() << "setter" << inheritedName; @@ -1395,12 +1481,11 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, QualType PropertyIvarType = property->getType().getNonReferenceType(); bool compat = Context.hasSameType(PropertyIvarType, GetterType); if (!compat) { - if (isa<ObjCObjectPointerType>(PropertyIvarType) && - isa<ObjCObjectPointerType>(GetterType)) - compat = - Context.canAssignObjCInterfaces( - GetterType->getAs<ObjCObjectPointerType>(), - PropertyIvarType->getAs<ObjCObjectPointerType>()); + const ObjCObjectPointerType *propertyObjCPtr = nullptr; + const ObjCObjectPointerType *getterObjCPtr = nullptr; + if ((propertyObjCPtr = PropertyIvarType->getAs<ObjCObjectPointerType>()) && + (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>())) + compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr); else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType) != Compatible) { Diag(Loc, diag::error_property_accessor_type) @@ -1438,6 +1523,11 @@ static void CollectImmediateProperties(ObjCContainerDecl *CDecl, if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { for (auto *Prop : IDecl->properties()) PropMap[Prop->getIdentifier()] = Prop; + + // Collect the properties from visible extensions. + for (auto *Ext : IDecl->visible_extensions()) + CollectImmediateProperties(Ext, PropMap, SuperPropMap, IncludeProtocols); + if (IncludeProtocols) { // Scan through class's protocols. for (auto *PI : IDecl->all_referenced_protocols()) @@ -1445,9 +1535,8 @@ static void CollectImmediateProperties(ObjCContainerDecl *CDecl, } } if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { - if (!CATDecl->IsClassExtension()) - for (auto *Prop : CATDecl->properties()) - PropMap[Prop->getIdentifier()] = Prop; + for (auto *Prop : CATDecl->properties()) + PropMap[Prop->getIdentifier()] = Prop; if (IncludeProtocols) { // Scan through class's protocols. for (auto *PI : CATDecl->protocols()) @@ -1507,6 +1596,14 @@ Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, (Property->getPropertyIvarDecl() == IV)) return true; } + // Also look up property declaration in class extension whose one of its + // accessors is implemented by this method. + for (const auto *Ext : IFace->known_extensions()) + for (const auto *Property : Ext->properties()) + if ((Property->getGetterName() == IMD->getSelector() || + Property->getSetterName() == IMD->getSelector()) && + (Property->getPropertyIvarDecl() == IV)) + return true; return false; } @@ -1563,7 +1660,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) << Prop->getIdentifier(); - if (!PID->getLocation().isInvalid()) + if (PID->getLocation().isValid()) Diag(PID->getLocation(), diag::note_property_synthesize); continue; } @@ -1791,11 +1888,20 @@ void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) void Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, - ObjCContainerDecl* IDecl) { + ObjCInterfaceDecl* IDecl) { // Rules apply in non-GC mode only if (getLangOpts().getGC() != LangOptions::NonGC) return; - for (const auto *Property : IDecl->properties()) { + ObjCContainerDecl::PropertyMap PM; + for (auto *Prop : IDecl->properties()) + PM[Prop->getIdentifier()] = Prop; + for (const auto *Ext : IDecl->known_extensions()) + for (auto *Prop : Ext->properties()) + PM[Prop->getIdentifier()] = Prop; + + for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end(); + I != E; ++I) { + const ObjCPropertyDecl *Property = I->second; ObjCMethodDecl *GetterMethod = nullptr; ObjCMethodDecl *SetterMethod = nullptr; bool LookedUpGetterSetter = false; @@ -1842,30 +1948,23 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, << Property->getIdentifier() << (GetterMethod != nullptr) << (SetterMethod != nullptr); // fixit stuff. - if (!AttributesAsWritten) { - if (Property->getLParenLoc().isValid()) { - // @property () ... case. - SourceRange PropSourceRange(Property->getAtLoc(), - Property->getLParenLoc()); - Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << - FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic"); - } - else { - //@property id etc. - SourceLocation endLoc = - Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); - endLoc = endLoc.getLocWithOffset(-1); - SourceRange PropSourceRange(Property->getAtLoc(), endLoc); - Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << - FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) "); - } - } - else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) { + if (Property->getLParenLoc().isValid() && + !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) { // @property () ... case. - SourceLocation endLoc = Property->getLParenLoc(); - SourceRange PropSourceRange(Property->getAtLoc(), endLoc); - Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << - FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, "); + SourceLocation AfterLParen = + getLocForEndOfToken(Property->getLParenLoc()); + StringRef NonatomicStr = AttributesAsWritten? "nonatomic, " + : "nonatomic"; + Diag(Property->getLocation(), + diag::note_atomic_property_fixup_suggest) + << FixItHint::CreateInsertion(AfterLParen, NonatomicStr); + } else if (Property->getLParenLoc().isInvalid()) { + //@property id etc. + SourceLocation startLoc = + Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); + Diag(Property->getLocation(), + diag::note_atomic_property_fixup_suggest) + << FixItHint::CreateInsertion(startLoc, "(nonatomic) "); } else Diag(MethodLoc, diag::note_atomic_property_fixup_suggest); @@ -1950,10 +2049,16 @@ void Sema::DiagnoseMissingDesignatedInitOverrides( I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) { const ObjCMethodDecl *MD = *I; if (!InitSelSet.count(MD->getSelector())) { - Diag(ImplD->getLocation(), - diag::warn_objc_implementation_missing_designated_init_override) - << MD->getSelector(); - Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here); + bool Ignore = false; + if (auto *IMD = IFD->getInstanceMethod(MD->getSelector())) { + Ignore = IMD->isUnavailable(); + } + if (!Ignore) { + Diag(ImplD->getLocation(), + diag::warn_objc_implementation_missing_designated_init_override) + << MD->getSelector(); + Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here); + } } } } @@ -1974,20 +2079,28 @@ static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods /// have the property type and issue diagnostics if they don't. /// Also synthesize a getter/setter method if none exist (and update the -/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized -/// methods is the "right" thing to do. -void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, - ObjCContainerDecl *CD, - ObjCPropertyDecl *redeclaredProperty, - ObjCContainerDecl *lexicalDC) { - +/// appropriate lookup tables. +void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { ObjCMethodDecl *GetterMethod, *SetterMethod; - + ObjCContainerDecl *CD = cast<ObjCContainerDecl>(property->getDeclContext()); if (CD->isInvalidDecl()) return; GetterMethod = CD->getInstanceMethod(property->getGetterName()); + // if setter or getter is not found in class extension, it might be + // in the primary class. + if (!GetterMethod) + if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) + if (CatDecl->IsClassExtension()) + GetterMethod = CatDecl->getClassInterface()-> + getInstanceMethod(property->getGetterName()); + SetterMethod = CD->getInstanceMethod(property->getSetterName()); + if (!SetterMethod) + if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) + if (CatDecl->IsClassExtension()) + SetterMethod = CatDecl->getClassInterface()-> + getInstanceMethod(property->getSetterName()); DiagnosePropertyAccessorMismatch(property, GetterMethod, property->getLocation()); @@ -2020,9 +2133,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, // No instance method of same name as property getter name was found. // Declare a getter method and add it to the list of methods // for this class. - SourceLocation Loc = redeclaredProperty ? - redeclaredProperty->getLocation() : - property->getLocation(); + SourceLocation Loc = property->getLocation(); // If the property is null_resettable, the getter returns nonnull. QualType resultTy = property->getType(); @@ -2050,10 +2161,6 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, AddPropertyAttrs(*this, GetterMethod, property); - // FIXME: Eventually this shouldn't be needed, as the lexical context - // and the real context should be the same. - if (lexicalDC) - GetterMethod->setLexicalDeclContext(lexicalDC); if (property->hasAttr<NSReturnsNotRetainedAttr>()) GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context, Loc)); @@ -2082,9 +2189,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, // No instance method of same name as property setter name was found. // Declare a setter method and add it to the list of methods // for this class. - SourceLocation Loc = redeclaredProperty ? - redeclaredProperty->getLocation() : - property->getLocation(); + SourceLocation Loc = property->getLocation(); SetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, @@ -2126,10 +2231,6 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, AddPropertyAttrs(*this, SetterMethod, property); CD->addDecl(SetterMethod); - // FIXME: Eventually this shouldn't be needed, as the lexical context - // and the real context should be the same. - if (lexicalDC) - SetterMethod->setLexicalDeclContext(lexicalDC); if (const SectionAttr *SA = property->getAttr<SectionAttr>()) SetterMethod->addAttr( SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section, @@ -2189,15 +2290,6 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); QualType PropertyTy = PropertyDecl->getType(); - unsigned PropertyOwnership = getOwnershipRule(Attributes); - - // 'readonly' property with no obvious lifetime. - // its life time will be determined by its backing ivar. - if (getLangOpts().ObjCAutoRefCount && - Attributes & ObjCDeclSpec::DQ_PR_readonly && - PropertyTy->isObjCRetainableType() && - !PropertyOwnership) - return; // Check for copy or retain on non-object types. if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | @@ -2295,13 +2387,6 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, if (*nullability == NullabilityKind::NonNull) Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "nonnull" << "weak"; - } else { - PropertyTy = - Context.getAttributedType( - AttributedType::getNullabilityAttrKind(NullabilityKind::Nullable), - PropertyTy, PropertyTy); - TypeSourceInfo *TSInfo = PropertyDecl->getTypeSourceInfo(); - PropertyDecl->setType(PropertyTy, TSInfo); } } @@ -2314,16 +2399,14 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, // Warn if user supplied no assignment attribute, property is // readwrite, and this is an object type. - if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_unsafe_unretained | - ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong | - ObjCDeclSpec::DQ_PR_weak)) && - PropertyTy->isObjCObjectPointerType()) { - if (getLangOpts().ObjCAutoRefCount) - // With arc, @property definitions should default to (strong) when - // not specified; including when property is 'readonly'. - PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); - else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) { + if (!getOwnershipRule(Attributes) && PropertyTy->isObjCRetainableType()) { + if (Attributes & ObjCDeclSpec::DQ_PR_readonly) { + // do nothing + } else if (getLangOpts().ObjCAutoRefCount) { + // With arc, @property definitions should default to strong when + // not specified. + PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + } else if (PropertyTy->isObjCObjectPointerType()) { bool isAnyClassTy = (PropertyTy->isObjCClassType() || PropertyTy->isObjCQualifiedClassType()); @@ -2342,7 +2425,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, if (getLangOpts().getGC() == LangOptions::NonGC) Diag(Loc, diag::warn_objc_property_default_assign_on_object); } - } + } // FIXME: Implement warning dependent on NSCopying being // implemented. See also: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp index ca67a1c..5dd8354 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp @@ -77,6 +77,11 @@ public: ImplicitDSALoc() {} }; +public: + struct MapInfo { + Expr *RefExpr; + }; + private: struct DSAInfo { OpenMPClauseKind Attributes; @@ -84,33 +89,41 @@ private: }; typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy; typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy; - typedef llvm::DenseSet<VarDecl *> LoopControlVariablesSetTy; + typedef llvm::DenseMap<VarDecl *, unsigned> LoopControlVariablesMapTy; + typedef llvm::SmallDenseMap<VarDecl *, MapInfo, 64> MappedDeclsTy; + typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>> + CriticalsWithHintsTy; struct SharingMapTy { DeclSAMapTy SharingMap; AlignedMapTy AlignedMap; - LoopControlVariablesSetTy LCVSet; + MappedDeclsTy MappedDecls; + LoopControlVariablesMapTy LCVMap; DefaultDataSharingAttributes DefaultAttr; SourceLocation DefaultAttrLoc; OpenMPDirectiveKind Directive; DeclarationNameInfo DirectiveName; Scope *CurScope; SourceLocation ConstructLoc; - bool OrderedRegion; + /// \brief first argument (Expr *) contains optional argument of the + /// 'ordered' clause, the second one is true if the regions has 'ordered' + /// clause, false otherwise. + llvm::PointerIntPair<Expr *, 1, bool> OrderedRegion; bool NowaitRegion; - unsigned CollapseNumber; + bool CancelRegion; + unsigned AssociatedLoops; SourceLocation InnerTeamsRegionLoc; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) - : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified), + : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified), Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope), - ConstructLoc(Loc), OrderedRegion(false), NowaitRegion(false), - CollapseNumber(1), InnerTeamsRegionLoc() {} + ConstructLoc(Loc), OrderedRegion(), NowaitRegion(false), + CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {} SharingMapTy() - : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified), + : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified), Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr), - ConstructLoc(), OrderedRegion(false), NowaitRegion(false), - CollapseNumber(1), InnerTeamsRegionLoc() {} + ConstructLoc(), OrderedRegion(), NowaitRegion(false), + CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {} }; typedef SmallVector<SharingMapTy, 64> StackTy; @@ -122,6 +135,7 @@ private: OpenMPClauseKind ClauseKindMode; Sema &SemaRef; bool ForceCapturing; + CriticalsWithHintsTy Criticals; typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator; @@ -152,6 +166,16 @@ public: Stack.pop_back(); } + void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) { + Criticals[D->getDirectiveName().getAsString()] = std::make_pair(D, Hint); + } + const std::pair<OMPCriticalDirective *, llvm::APSInt> + getCriticalWithHint(const DeclarationNameInfo &Name) const { + auto I = Criticals.find(Name.getAsString()); + if (I != Criticals.end()) + return I->second; + return std::make_pair(nullptr, llvm::APSInt()); + } /// \brief If 'aligned' declaration for given variable \a D was not seen yet, /// add it and return NULL; otherwise return previous occurrence's expression /// for diagnostics. @@ -161,7 +185,17 @@ public: void addLoopControlVariable(VarDecl *D); /// \brief Check if the specified variable is a loop control variable for /// current region. - bool isLoopControlVariable(VarDecl *D); + /// \return The index of the loop control variable in the list of associated + /// for-loops (from outer to inner). + unsigned isLoopControlVariable(VarDecl *D); + /// \brief Check if the specified variable is a loop control variable for + /// parent region. + /// \return The index of the loop control variable in the list of associated + /// for-loops (from outer to inner). + unsigned isParentLoopControlVariable(VarDecl *D); + /// \brief Get the loop control variable for the I-th loop (or nullptr) in + /// parent directive. + VarDecl *getParentLoopControlVariable(unsigned I); /// \brief Adds explicit data sharing attribute to the specified declaration. void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A); @@ -190,6 +224,13 @@ public: bool hasExplicitDSA(VarDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, unsigned Level); + + /// \brief Returns true if the directive at level \Level matches in the + /// specified \a DPred predicate. + bool hasExplicitDirective( + const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, + unsigned Level); + /// \brief Finds a directive which matches specified \a DPred predicate. template <class NamedDirectivesPredicate> bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent); @@ -204,6 +245,8 @@ public: return Stack[Stack.size() - 2].Directive; return OMPD_unknown; } + /// \brief Return the directive associated with the provided scope. + OpenMPDirectiveKind getDirectiveForScope(const Scope *S) const; /// \brief Set default data sharing attribute to none. void setDefaultDSANone(SourceLocation Loc) { @@ -230,16 +273,23 @@ public: } /// \brief Marks current region as ordered (it has an 'ordered' clause). - void setOrderedRegion(bool IsOrdered = true) { - Stack.back().OrderedRegion = IsOrdered; + void setOrderedRegion(bool IsOrdered, Expr *Param) { + Stack.back().OrderedRegion.setInt(IsOrdered); + Stack.back().OrderedRegion.setPointer(Param); } /// \brief Returns true, if parent region is ordered (has associated /// 'ordered' clause), false - otherwise. bool isParentOrderedRegion() const { if (Stack.size() > 2) - return Stack[Stack.size() - 2].OrderedRegion; + return Stack[Stack.size() - 2].OrderedRegion.getInt(); return false; } + /// \brief Returns optional parameter for the ordered region. + Expr *getParentOrderedRegionParam() const { + if (Stack.size() > 2) + return Stack[Stack.size() - 2].OrderedRegion.getPointer(); + return nullptr; + } /// \brief Marks current region as nowait (it has a 'nowait' clause). void setNowaitRegion(bool IsNowait = true) { Stack.back().NowaitRegion = IsNowait; @@ -251,13 +301,21 @@ public: return Stack[Stack.size() - 2].NowaitRegion; return false; } + /// \brief Marks parent region as cancel region. + void setParentCancelRegion(bool Cancel = true) { + if (Stack.size() > 2) + Stack[Stack.size() - 2].CancelRegion = + Stack[Stack.size() - 2].CancelRegion || Cancel; + } + /// \brief Return true if current region has inner cancel construct. + bool isCancelRegion() const { + return Stack.back().CancelRegion; + } /// \brief Set collapse value for the region. - void setCollapseNumber(unsigned Val) { Stack.back().CollapseNumber = Val; } + void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops = Val; } /// \brief Return collapse value for region. - unsigned getCollapseNumber() const { - return Stack.back().CollapseNumber; - } + unsigned getAssociatedLoops() const { return Stack.back().AssociatedLoops; } /// \brief Marks current target region as one with closely nested teams /// region. @@ -279,10 +337,37 @@ public: Scope *getCurScope() const { return Stack.back().CurScope; } Scope *getCurScope() { return Stack.back().CurScope; } SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; } + + MapInfo getMapInfoForVar(VarDecl *VD) { + MapInfo VarMI = {0}; + for (auto Cnt = Stack.size() - 1; Cnt > 0; --Cnt) { + if (Stack[Cnt].MappedDecls.count(VD)) { + VarMI = Stack[Cnt].MappedDecls[VD]; + break; + } + } + return VarMI; + } + + void addMapInfoForVar(VarDecl *VD, MapInfo MI) { + if (Stack.size() > 1) { + Stack.back().MappedDecls[VD] = MI; + } + } + + MapInfo IsMappedInCurrentRegion(VarDecl *VD) { + assert(Stack.size() > 1 && "Target level is 0"); + MapInfo VarMI = {0}; + if (Stack.size() > 1 && Stack.back().MappedDecls.count(VD)) { + VarMI = Stack.back().MappedDecls[VD]; + } + return VarMI; + } }; bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) { return isOpenMPParallelDirective(DKind) || DKind == OMPD_task || - isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown; + isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown || + isOpenMPTaskLoopDirective(DKind); } } // namespace @@ -409,13 +494,32 @@ DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) { void DSAStackTy::addLoopControlVariable(VarDecl *D) { assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); D = D->getCanonicalDecl(); - Stack.back().LCVSet.insert(D); + Stack.back().LCVMap.insert(std::make_pair(D, Stack.back().LCVMap.size() + 1)); } -bool DSAStackTy::isLoopControlVariable(VarDecl *D) { +unsigned DSAStackTy::isLoopControlVariable(VarDecl *D) { assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); D = D->getCanonicalDecl(); - return Stack.back().LCVSet.count(D) > 0; + return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] : 0; +} + +unsigned DSAStackTy::isParentLoopControlVariable(VarDecl *D) { + assert(Stack.size() > 2 && "Data-sharing attributes stack is empty"); + D = D->getCanonicalDecl(); + return Stack[Stack.size() - 2].LCVMap.count(D) > 0 + ? Stack[Stack.size() - 2].LCVMap[D] + : 0; +} + +VarDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) { + assert(Stack.size() > 2 && "Data-sharing attributes stack is empty"); + if (Stack[Stack.size() - 2].LCVMap.size() < I) + return nullptr; + for (auto &Pair : Stack[Stack.size() - 2].LCVMap) { + if (Pair.second == I) + return Pair.first; + } + return nullptr; } void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) { @@ -452,12 +556,17 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) { /// \brief Build a variable declaration for OpenMP loop iteration variable. static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, - StringRef Name) { + StringRef Name, const AttrVec *Attrs = nullptr) { 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); + if (Attrs) { + for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end()); + I != E; ++I) + Decl->addAttr(*I); + } Decl->setImplicit(); return Decl; } @@ -496,41 +605,20 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { } // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced - // in a Construct, C/C++, predetermined, p.1] - // Variables with automatic storage duration that are declared in a scope - // inside the construct are private. - OpenMPDirectiveKind Kind = - FromParent ? getParentDirective() : getCurrentDirective(); - auto StartI = std::next(Stack.rbegin()); - auto EndI = std::prev(Stack.rend()); - if (FromParent && StartI != EndI) { - StartI = std::next(StartI); - } - if (!isParallelOrTaskRegion(Kind)) { - if (isOpenMPLocal(D, StartI) && - ((D->isLocalVarDecl() && (D->getStorageClass() == SC_Auto || - D->getStorageClass() == SC_None)) || - isa<ParmVarDecl>(D))) { - DVar.CKind = OMPC_private; + // 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()) { + DSAVarData DVarTemp = + hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent); + if (DVarTemp.CKind != OMPC_unknown && 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(); @@ -542,6 +630,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { // shared. CXXRecordDecl *RD = SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; + if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) + if (auto *CTD = CTSD->getSpecializedTemplate()) + RD = CTD->getTemplatedDecl(); if (IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) { // Variables with const-qualified type having no mutable member may be @@ -557,6 +648,11 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { // Explicitly specified attributes and local variables with predetermined // attributes. + auto StartI = std::next(Stack.rbegin()); + auto EndI = std::prev(Stack.rend()); + if (FromParent && StartI != EndI) { + StartI = std::next(StartI); + } auto I = std::prev(StartI); if (I->SharingMap.count(D)) { DVar.RefExpr = I->SharingMap[D].RefExpr; @@ -635,6 +731,19 @@ bool DSAStackTy::hasExplicitDSA( CPred(StartI->SharingMap[D].Attributes); } +bool DSAStackTy::hasExplicitDirective( + const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, + unsigned Level) { + if (isClauseParsingMode()) + ++Level; + auto StartI = Stack.rbegin(); + auto EndI = std::prev(Stack.rend()); + if (std::distance(StartI, EndI) <= (int)Level) + return false; + std::advance(StartI, Level); + return DPred(StartI->Directive); +} + template <class NamedDirectivesPredicate> bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) { auto StartI = std::next(Stack.rbegin()); @@ -649,15 +758,134 @@ bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) { return false; } +OpenMPDirectiveKind DSAStackTy::getDirectiveForScope(const Scope *S) const { + for (auto I = Stack.rbegin(), EE = Stack.rend(); I != EE; ++I) + if (I->CurScope == S) + return I->Directive; + return OMPD_unknown; +} + void Sema::InitDataSharingAttributesStack() { VarDataSharingAttributesStack = new DSAStackTy(*this); } #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) +bool Sema::IsOpenMPCapturedByRef(VarDecl *VD, + const CapturedRegionScopeInfo *RSI) { + assert(LangOpts.OpenMP && "OpenMP is not allowed"); + + auto &Ctx = getASTContext(); + bool IsByRef = true; + + // Find the directive that is associated with the provided scope. + auto DKind = DSAStack->getDirectiveForScope(RSI->TheScope); + auto Ty = VD->getType(); + + if (isOpenMPTargetDirective(DKind)) { + // This table summarizes how a given variable should be passed to the device + // given its type and the clauses where it appears. This table is based on + // the description in OpenMP 4.5 [2.10.4, target Construct] and + // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses]. + // + // ========================================================================= + // | type | defaultmap | pvt | first | is_device_ptr | map | res. | + // | |(tofrom:scalar)| | pvt | | | | + // ========================================================================= + // | scl | | | | - | | bycopy| + // | scl | | - | x | - | - | bycopy| + // | scl | | x | - | - | - | null | + // | scl | x | | | - | | byref | + // | scl | x | - | x | - | - | bycopy| + // | scl | x | x | - | - | - | null | + // | scl | | - | - | - | x | byref | + // | scl | x | - | - | - | x | byref | + // + // | agg | n.a. | | | - | | byref | + // | agg | n.a. | - | x | - | - | byref | + // | agg | n.a. | x | - | - | - | null | + // | agg | n.a. | - | - | - | x | byref | + // | agg | n.a. | - | - | - | x[] | byref | + // + // | ptr | n.a. | | | - | | bycopy| + // | ptr | n.a. | - | x | - | - | bycopy| + // | ptr | n.a. | x | - | - | - | null | + // | ptr | n.a. | - | - | - | x | byref | + // | ptr | n.a. | - | - | - | x[] | bycopy| + // | ptr | n.a. | - | - | x | | bycopy| + // | ptr | n.a. | - | - | x | x | bycopy| + // | ptr | n.a. | - | - | x | x[] | bycopy| + // ========================================================================= + // Legend: + // scl - scalar + // ptr - pointer + // agg - aggregate + // x - applies + // - - invalid in this combination + // [] - mapped with an array section + // byref - should be mapped by reference + // byval - should be mapped by value + // null - initialize a local variable to null on the device + // + // Observations: + // - All scalar declarations that show up in a map clause have to be passed + // by reference, because they may have been mapped in the enclosing data + // environment. + // - If the scalar value does not fit the size of uintptr, it has to be + // passed by reference, regardless the result in the table above. + // - For pointers mapped by value that have either an implicit map or an + // array section, the runtime library may pass the NULL value to the + // device instead of the value passed to it by the compiler. + + // FIXME: Right now, only implicit maps are implemented. Properly mapping + // values requires having the map, private, and firstprivate clauses SEMA + // and parsing in place, which we don't yet. + + if (Ty->isReferenceType()) + Ty = Ty->castAs<ReferenceType>()->getPointeeType(); + IsByRef = !Ty->isScalarType(); + } + + // When passing data by value, we need to make sure it fits the uintptr size + // and alignment, because the runtime library only deals with uintptr types. + // If it does not fit the uintptr size, we need to pass the data by reference + // instead. + if (!IsByRef && + (Ctx.getTypeSizeInChars(Ty) > + Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || + Ctx.getDeclAlign(VD) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) + IsByRef = true; + + return IsByRef; +} + bool Sema::IsOpenMPCapturedVar(VarDecl *VD) { assert(LangOpts.OpenMP && "OpenMP is not allowed"); VD = VD->getCanonicalDecl(); + + // If we are attempting to capture a global variable in a directive with + // 'target' we return true so that this global is also mapped to the device. + // + // FIXME: If the declaration is enclosed in a 'declare target' directive, + // then it should not be captured. Therefore, an extra check has to be + // inserted here once support for 'declare target' is added. + // + if (!VD->hasLocalStorage()) { + if (DSAStack->getCurrentDirective() == OMPD_target && + !DSAStack->isClauseParsingMode()) { + return true; + } + if (DSAStack->getCurScope() && + DSAStack->hasDirective( + [](OpenMPDirectiveKind K, const DeclarationNameInfo &DNI, + SourceLocation Loc) -> bool { + return isOpenMPTargetDirective(K); + }, + false)) { + return true; + } + } + if (DSAStack->getCurrentDirective() != OMPD_unknown && (!DSAStack->isClauseParsingMode() || DSAStack->getParentDirective() != OMPD_unknown)) { @@ -682,6 +910,14 @@ bool Sema::isOpenMPPrivateVar(VarDecl *VD, unsigned Level) { VD, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level); } +bool Sema::isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level) { + assert(LangOpts.OpenMP && "OpenMP is not allowed"); + // Return true if the current level is no longer enclosed in a target region. + + return !VD->hasLocalStorage() && + DSAStack->hasExplicitDirective(isOpenMPTargetDirective, Level); +} + void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; } void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, @@ -715,7 +951,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { continue; } auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl()); - QualType Type = VD->getType(); + QualType Type = VD->getType().getNonReferenceType(); auto DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind == OMPC_lastprivate) { // Generate helper private variable and initialize it with the @@ -723,9 +959,9 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { // 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()); + auto *VDPrivate = buildVarDecl( + *this, DE->getExprLoc(), Type.getUnqualifiedType(), + VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr); ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); if (VDPrivate->isInvalidDecl()) continue; @@ -1158,7 +1394,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { switch (DKind) { case OMPD_parallel: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); - QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); + QualType KmpInt32PtrTy = + Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); Sema::CapturedParamNameType Params[] = { std::make_pair(".global_tid.", KmpInt32PtrTy), std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1234,7 +1471,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { } case OMPD_parallel_for: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); - QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); + QualType KmpInt32PtrTy = + Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); Sema::CapturedParamNameType Params[] = { std::make_pair(".global_tid.", KmpInt32PtrTy), std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1246,7 +1484,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { } case OMPD_parallel_for_simd: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); - QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); + QualType KmpInt32PtrTy = + Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); Sema::CapturedParamNameType Params[] = { std::make_pair(".global_tid.", KmpInt32PtrTy), std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1258,7 +1497,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { } case OMPD_parallel_sections: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); - QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); + QualType KmpInt32PtrTy = + Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); Sema::CapturedParamNameType Params[] = { std::make_pair(".global_tid.", KmpInt32PtrTy), std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1309,6 +1549,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_target_data: case OMPD_target: { Sema::CapturedParamNameType Params[] = { std::make_pair(StringRef(), QualType()) // __context with shared vars @@ -1319,7 +1560,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { } case OMPD_teams: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); - QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); + QualType KmpInt32PtrTy = + Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); Sema::CapturedParamNameType Params[] = { std::make_pair(".global_tid.", KmpInt32PtrTy), std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1337,6 +1579,30 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_taskloop: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } + case OMPD_taskloop_simd: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } + case OMPD_distribute: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } case OMPD_threadprivate: case OMPD_taskyield: case OMPD_barrier: @@ -1356,6 +1622,10 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, ActOnCapturedRegionError(); return StmtError(); } + + OMPOrderedClause *OC = nullptr; + OMPScheduleClause *SC = nullptr; + SmallVector<OMPLinearClause *, 4> LCs; // This is required for proper codegen. for (auto *Clause : Clauses) { if (isOpenMPPrivate(Clause->getClauseKind()) || @@ -1377,10 +1647,42 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, // 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); - } + cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) + MarkDeclarationsReferencedInExpr(E); } + if (Clause->getClauseKind() == OMPC_schedule) + SC = cast<OMPScheduleClause>(Clause); + else if (Clause->getClauseKind() == OMPC_ordered) + OC = cast<OMPOrderedClause>(Clause); + else if (Clause->getClauseKind() == OMPC_linear) + LCs.push_back(cast<OMPLinearClause>(Clause)); + } + bool ErrorFound = false; + // OpenMP, 2.7.1 Loop Construct, Restrictions + // The nonmonotonic modifier cannot be specified if an ordered clause is + // specified. + if (SC && + (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic || + SC->getSecondScheduleModifier() == + OMPC_SCHEDULE_MODIFIER_nonmonotonic) && + OC) { + Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic + ? SC->getFirstScheduleModifierLoc() + : SC->getSecondScheduleModifierLoc(), + diag::err_omp_schedule_nonmonotonic_ordered) + << SourceRange(OC->getLocStart(), OC->getLocEnd()); + ErrorFound = true; + } + if (!LCs.empty() && OC && OC->getNumForLoops()) { + for (auto *C : LCs) { + Diag(C->getLocStart(), diag::err_omp_linear_ordered) + << SourceRange(OC->getLocStart(), OC->getLocEnd()); + } + ErrorFound = true; + } + if (ErrorFound) { + ActOnCapturedRegionError(); + return StmtError(); } return ActOnCapturedRegionEnd(S.get()); } @@ -1419,6 +1721,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | cancellation | | // | | point | ! | // | parallel | cancel | ! | + // | parallel | taskloop | * | + // | parallel | taskloop simd | * | + // | parallel | distribute | | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -1445,6 +1750,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | cancellation | | // | | point | ! | // | for | cancel | ! | + // | for | taskloop | * | + // | for | taskloop simd | * | + // | for | distribute | | // +------------------+-----------------+------------------------------------+ // | master | parallel | * | // | master | for | + | @@ -1471,6 +1779,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | cancellation | | // | | point | | // | master | cancel | | + // | master | taskloop | * | + // | master | taskloop simd | * | + // | master | distribute | | // +------------------+-----------------+------------------------------------+ // | critical | parallel | * | // | critical | for | + | @@ -1496,6 +1807,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | critical | cancellation | | // | | point | | // | critical | cancel | | + // | critical | taskloop | * | + // | critical | taskloop simd | * | + // | critical | distribute | | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -1515,13 +1829,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | taskwait | | // | simd | taskgroup | | // | simd | flush | | - // | simd | ordered | | + // | simd | ordered | + (with simd clause) | // | simd | atomic | | // | simd | target | | // | simd | teams | | // | simd | cancellation | | // | | point | | // | simd | cancel | | + // | simd | taskloop | | + // | simd | taskloop simd | | + // | simd | distribute | | // +------------------+-----------------+------------------------------------+ // | for simd | parallel | | // | for simd | for | | @@ -1541,13 +1858,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for simd | taskwait | | // | for simd | taskgroup | | // | for simd | flush | | - // | for simd | ordered | | + // | for simd | ordered | + (with simd clause) | // | for simd | atomic | | // | for simd | target | | // | for simd | teams | | // | for simd | cancellation | | // | | point | | // | for simd | cancel | | + // | for simd | taskloop | | + // | for simd | taskloop simd | | + // | for simd | distribute | | // +------------------+-----------------+------------------------------------+ // | parallel for simd| parallel | | // | parallel for simd| for | | @@ -1567,13 +1887,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for simd| taskwait | | // | parallel for simd| taskgroup | | // | parallel for simd| flush | | - // | parallel for simd| ordered | | + // | parallel for simd| ordered | + (with simd clause) | // | parallel for simd| atomic | | // | parallel for simd| target | | // | parallel for simd| teams | | // | parallel for simd| cancellation | | // | | point | | // | parallel for simd| cancel | | + // | parallel for simd| taskloop | | + // | parallel for simd| taskloop simd | | + // | parallel for simd| distribute | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1600,6 +1923,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | cancellation | | // | | point | ! | // | sections | cancel | ! | + // | sections | taskloop | * | + // | sections | taskloop simd | * | + // | sections | distribute | | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1626,6 +1952,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | cancellation | | // | | point | ! | // | section | cancel | ! | + // | section | taskloop | * | + // | section | taskloop simd | * | + // | section | distribute | | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1652,6 +1981,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | cancellation | | // | | point | | // | single | cancel | | + // | single | taskloop | * | + // | single | taskloop simd | * | + // | single | distribute | | // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | @@ -1678,6 +2010,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for | cancellation | | // | | point | ! | // | parallel for | cancel | ! | + // | parallel for | taskloop | * | + // | parallel for | taskloop simd | * | + // | parallel for | distribute | | // +------------------+-----------------+------------------------------------+ // | parallel sections| parallel | * | // | parallel sections| for | + | @@ -1704,6 +2039,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| cancellation | | // | | point | ! | // | parallel sections| cancel | ! | + // | parallel sections| taskloop | * | + // | parallel sections| taskloop simd | * | + // | parallel sections| distribute | | // +------------------+-----------------+------------------------------------+ // | task | parallel | * | // | task | for | + | @@ -1730,6 +2068,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task | cancellation | | // | | point | ! | // | task | cancel | ! | + // | task | taskloop | * | + // | task | taskloop simd | * | + // | task | distribute | | // +------------------+-----------------+------------------------------------+ // | ordered | parallel | * | // | ordered | for | + | @@ -1756,6 +2097,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | ordered | cancellation | | // | | point | | // | ordered | cancel | | + // | ordered | taskloop | * | + // | ordered | taskloop simd | * | + // | ordered | distribute | | // +------------------+-----------------+------------------------------------+ // | atomic | parallel | | // | atomic | for | | @@ -1782,6 +2126,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | atomic | cancellation | | // | | point | | // | atomic | cancel | | + // | atomic | taskloop | | + // | atomic | taskloop simd | | + // | atomic | distribute | | // +------------------+-----------------+------------------------------------+ // | target | parallel | * | // | target | for | * | @@ -1808,6 +2155,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | target | cancellation | | // | | point | | // | target | cancel | | + // | target | taskloop | * | + // | target | taskloop simd | * | + // | target | distribute | | // +------------------+-----------------+------------------------------------+ // | teams | parallel | * | // | teams | for | + | @@ -1834,6 +2184,95 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | teams | cancellation | | // | | point | | // | teams | cancel | | + // | teams | taskloop | + | + // | teams | taskloop simd | + | + // | teams | distribute | ! | + // +------------------+-----------------+------------------------------------+ + // | taskloop | parallel | * | + // | taskloop | for | + | + // | taskloop | for simd | + | + // | taskloop | master | + | + // | taskloop | critical | * | + // | taskloop | simd | * | + // | taskloop | sections | + | + // | taskloop | section | + | + // | taskloop | single | + | + // | taskloop | parallel for | * | + // | taskloop |parallel for simd| * | + // | taskloop |parallel sections| * | + // | taskloop | task | * | + // | taskloop | taskyield | * | + // | taskloop | barrier | + | + // | taskloop | taskwait | * | + // | taskloop | taskgroup | * | + // | taskloop | flush | * | + // | taskloop | ordered | + | + // | taskloop | atomic | * | + // | taskloop | target | * | + // | taskloop | teams | + | + // | taskloop | cancellation | | + // | | point | | + // | taskloop | cancel | | + // | taskloop | taskloop | * | + // | taskloop | distribute | | + // +------------------+-----------------+------------------------------------+ + // | taskloop simd | parallel | | + // | taskloop simd | for | | + // | taskloop simd | for simd | | + // | taskloop simd | master | | + // | taskloop simd | critical | | + // | taskloop simd | simd | | + // | taskloop simd | sections | | + // | taskloop simd | section | | + // | taskloop simd | single | | + // | taskloop simd | parallel for | | + // | taskloop simd |parallel for simd| | + // | taskloop simd |parallel sections| | + // | taskloop simd | task | | + // | taskloop simd | taskyield | | + // | taskloop simd | barrier | | + // | taskloop simd | taskwait | | + // | taskloop simd | taskgroup | | + // | taskloop simd | flush | | + // | taskloop simd | ordered | + (with simd clause) | + // | taskloop simd | atomic | | + // | taskloop simd | target | | + // | taskloop simd | teams | | + // | taskloop simd | cancellation | | + // | | point | | + // | taskloop simd | cancel | | + // | taskloop simd | taskloop | | + // | taskloop simd | taskloop simd | | + // | taskloop simd | distribute | | + // +------------------+-----------------+------------------------------------+ + // | distribute | parallel | * | + // | distribute | for | * | + // | distribute | for simd | * | + // | distribute | master | * | + // | distribute | critical | * | + // | distribute | simd | * | + // | distribute | sections | * | + // | distribute | section | * | + // | distribute | single | * | + // | distribute | parallel for | * | + // | distribute |parallel for simd| * | + // | distribute |parallel sections| * | + // | distribute | task | * | + // | distribute | taskyield | * | + // | distribute | barrier | * | + // | distribute | taskwait | * | + // | distribute | taskgroup | * | + // | distribute | flush | * | + // | distribute | ordered | + | + // | distribute | atomic | * | + // | distribute | target | | + // | distribute | teams | | + // | distribute | cancellation | + | + // | | point | | + // | distribute | cancel | + | + // | distribute | taskloop | * | + // | distribute | taskloop simd | * | + // | distribute | distribute | | // +------------------+-----------------+------------------------------------+ if (Stack->getCurScope()) { auto ParentRegion = Stack->getParentDirective(); @@ -1843,11 +2282,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, NoRecommend, ShouldBeInParallelRegion, ShouldBeInOrderedRegion, - ShouldBeInTargetRegion + ShouldBeInTargetRegion, + ShouldBeInTeamsRegion } Recommend = NoRecommend; - if (isOpenMPSimdDirective(ParentRegion)) { + if (isOpenMPSimdDirective(ParentRegion) && CurrentRegion != OMPD_ordered) { // OpenMP [2.16, Nesting of Regions] // OpenMP constructs may not be nested inside a simd region. + // OpenMP [2.8.1,simd Construct, Restrictions] + // An ordered construct with the simd clause is the only OpenMP construct + // that can appear in the simd region. SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd); return true; } @@ -1890,16 +2333,19 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // construct-type-clause. NestingProhibited = !((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) || - (CancelRegion == OMPD_for && ParentRegion == OMPD_for) || + (CancelRegion == OMPD_for && + (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for)) || (CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) || (CancelRegion == OMPD_sections && - (ParentRegion == OMPD_section || ParentRegion == OMPD_sections))); + (ParentRegion == OMPD_section || ParentRegion == OMPD_sections || + ParentRegion == OMPD_parallel_sections))); } else if (CurrentRegion == OMPD_master) { // OpenMP [2.16, Nesting of Regions] // A master region may not be closely nested inside a worksharing, // atomic, or explicit task region. NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || - ParentRegion == OMPD_task; + ParentRegion == OMPD_task || + isOpenMPTaskLoopDirective(ParentRegion); } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) { // OpenMP [2.16, Nesting of Regions] // A critical region may not be nested (closely or otherwise) inside a @@ -1936,7 +2382,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || ParentRegion == OMPD_task || ParentRegion == OMPD_master || - ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered; + ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered || + isOpenMPTaskLoopDirective(ParentRegion); } else if (isOpenMPWorksharingDirective(CurrentRegion) && !isOpenMPParallelDirective(CurrentRegion)) { // OpenMP [2.16, Nesting of Regions] @@ -1945,7 +2392,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || ParentRegion == OMPD_task || ParentRegion == OMPD_master || - ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered; + ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered || + isOpenMPTaskLoopDirective(ParentRegion); Recommend = ShouldBeInParallelRegion; } else if (CurrentRegion == OMPD_ordered) { // OpenMP [2.16, Nesting of Regions] @@ -1953,9 +2401,14 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // atomic, or explicit task region. // An ordered region must be closely nested inside a loop region (or // parallel loop region) with an ordered clause. + // OpenMP [2.8.1,simd Construct, Restrictions] + // An ordered construct with the simd clause is the only OpenMP construct + // that can appear in the simd region. NestingProhibited = ParentRegion == OMPD_critical || ParentRegion == OMPD_task || - !Stack->isParentOrderedRegion(); + isOpenMPTaskLoopDirective(ParentRegion) || + !(isOpenMPSimdDirective(ParentRegion) || + Stack->isParentOrderedRegion()); Recommend = ShouldBeInOrderedRegion; } else if (isOpenMPTeamsDirective(CurrentRegion)) { // OpenMP [2.16, Nesting of Regions] @@ -1970,10 +2423,17 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // distribute, parallel, parallel sections, parallel workshare, and the // parallel loop and parallel loop SIMD constructs are the only OpenMP // constructs that can be closely nested in the teams region. - // TODO: add distribute directive. - NestingProhibited = !isOpenMPParallelDirective(CurrentRegion); + NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) && + !isOpenMPDistributeDirective(CurrentRegion); Recommend = ShouldBeInParallelRegion; } + if (!NestingProhibited && isOpenMPDistributeDirective(CurrentRegion)) { + // OpenMP 4.5 [2.17 Nesting of Regions] + // The region associated with the distribute construct must be strictly + // nested inside a teams region + NestingProhibited = !isOpenMPTeamsDirective(ParentRegion); + Recommend = ShouldBeInTeamsRegion; + } if (NestingProhibited) { SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) << CloseNesting << getOpenMPDirectiveName(ParentRegion) << Recommend @@ -1984,6 +2444,88 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, return false; } +static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, + ArrayRef<OMPClause *> Clauses, + ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) { + bool ErrorFound = false; + unsigned NamedModifiersNumber = 0; + SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers( + OMPD_unknown + 1); + SmallVector<SourceLocation, 4> NameModifierLoc; + for (const auto *C : Clauses) { + if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) { + // At most one if clause without a directive-name-modifier can appear on + // the directive. + OpenMPDirectiveKind CurNM = IC->getNameModifier(); + if (FoundNameModifiers[CurNM]) { + S.Diag(C->getLocStart(), diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if) + << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM); + ErrorFound = true; + } else if (CurNM != OMPD_unknown) { + NameModifierLoc.push_back(IC->getNameModifierLoc()); + ++NamedModifiersNumber; + } + FoundNameModifiers[CurNM] = IC; + if (CurNM == OMPD_unknown) + continue; + // Check if the specified name modifier is allowed for the current + // directive. + // At most one if clause with the particular directive-name-modifier can + // appear on the directive. + bool MatchFound = false; + for (auto NM : AllowedNameModifiers) { + if (CurNM == NM) { + MatchFound = true; + break; + } + } + if (!MatchFound) { + S.Diag(IC->getNameModifierLoc(), + diag::err_omp_wrong_if_directive_name_modifier) + << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind); + ErrorFound = true; + } + } + } + // If any if clause on the directive includes a directive-name-modifier then + // all if clauses on the directive must include a directive-name-modifier. + if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) { + if (NamedModifiersNumber == AllowedNameModifiers.size()) { + S.Diag(FoundNameModifiers[OMPD_unknown]->getLocStart(), + diag::err_omp_no_more_if_clause); + } else { + std::string Values; + std::string Sep(", "); + unsigned AllowedCnt = 0; + unsigned TotalAllowedNum = + AllowedNameModifiers.size() - NamedModifiersNumber; + for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End; + ++Cnt) { + OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt]; + if (!FoundNameModifiers[NM]) { + Values += "'"; + Values += getOpenMPDirectiveName(NM); + Values += "'"; + if (AllowedCnt + 2 == TotalAllowedNum) + Values += " or "; + else if (AllowedCnt + 1 != TotalAllowedNum) + Values += Sep; + ++AllowedCnt; + } + } + S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(), + diag::err_omp_unnamed_if_clause) + << (TotalAllowedNum > 1) << Values; + } + for (auto Loc : NameModifierLoc) { + S.Diag(Loc, diag::note_omp_previous_named_if_clause); + } + ErrorFound = true; + } + return ErrorFound; +} + StmtResult Sema::ActOnOpenMPExecutableDirective( OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, @@ -2020,10 +2562,12 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( } } + llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers; switch (Kind) { case OMPD_parallel: Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); + AllowedNameModifiers.push_back(OMPD_parallel); break; case OMPD_simd: Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, @@ -2056,25 +2600,28 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc); break; case OMPD_critical: - assert(ClausesWithImplicit.empty() && - "No clauses are allowed for 'omp critical' directive"); - Res = ActOnOpenMPCriticalDirective(DirName, AStmt, StartLoc, EndLoc); + Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt, + StartLoc, EndLoc); break; case OMPD_parallel_for: Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + AllowedNameModifiers.push_back(OMPD_parallel); break; case OMPD_parallel_for_simd: Res = ActOnOpenMPParallelForSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + AllowedNameModifiers.push_back(OMPD_parallel); break; case OMPD_parallel_sections: Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); + AllowedNameModifiers.push_back(OMPD_parallel); break; case OMPD_task: Res = ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); + AllowedNameModifiers.push_back(OMPD_task); break; case OMPD_taskyield: assert(ClausesWithImplicit.empty() && @@ -2108,9 +2655,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc); break; case OMPD_ordered: - assert(ClausesWithImplicit.empty() && - "No clauses are allowed for 'omp ordered' directive"); - Res = ActOnOpenMPOrderedDirective(AStmt, StartLoc, EndLoc); + Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc); break; case OMPD_atomic: Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc, @@ -2123,6 +2669,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_target: Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); + AllowedNameModifiers.push_back(OMPD_target); break; case OMPD_cancellation_point: assert(ClausesWithImplicit.empty() && @@ -2132,11 +2679,30 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion); break; case OMPD_cancel: - assert(ClausesWithImplicit.empty() && - "No clauses are allowed for 'omp cancel' directive"); assert(AStmt == nullptr && "No associated statement allowed for 'omp cancel' directive"); - Res = ActOnOpenMPCancelDirective(StartLoc, EndLoc, CancelRegion); + Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc, + CancelRegion); + AllowedNameModifiers.push_back(OMPD_cancel); + break; + case OMPD_target_data: + Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc); + AllowedNameModifiers.push_back(OMPD_target_data); + break; + case OMPD_taskloop: + Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc, VarsWithInheritedDSA); + AllowedNameModifiers.push_back(OMPD_taskloop); + break; + case OMPD_taskloop_simd: + Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc, VarsWithInheritedDSA); + AllowedNameModifiers.push_back(OMPD_taskloop); + break; + case OMPD_distribute: + Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc, VarsWithInheritedDSA); break; case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); @@ -2148,8 +2714,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable) << P.first << P.second->getSourceRange(); } - if (!VarsWithInheritedDSA.empty()) - return StmtError(); + ErrorFound = !VarsWithInheritedDSA.empty() || ErrorFound; + + if (!AllowedNameModifiers.empty()) + ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) || + ErrorFound; if (ErrorFound) return StmtError(); @@ -2160,7 +2729,9 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + CapturedStmt *CS = cast<CapturedStmt>(AStmt); // 1.2.2 OpenMP Language Terminology // Structured block - An executable statement with a single entry at the @@ -2171,8 +2742,8 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); - return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, - AStmt); + return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, + DSAStack->isCancelRegion()); } namespace { @@ -2247,6 +2818,9 @@ public: Expr *BuildPreCond(Scope *S, Expr *Cond) const; /// \brief Build reference expression to the counter be used for codegen. Expr *BuildCounterVar() const; + /// \brief Build reference expression to the private counter be used for + /// codegen. + Expr *BuildPrivateCounterVar() const; /// \brief Build initization of the counter be used for codegen. Expr *BuildCounterInit() const; /// \brief Build step of the counter be used for codegen. @@ -2261,8 +2835,8 @@ private: /// \brief Helper to set loop counter variable and its initializer. bool SetVarAndLB(VarDecl *NewVar, DeclRefExpr *NewVarRefExpr, Expr *NewLB); /// \brief Helper to set upper bound. - bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, const SourceRange &SR, - const SourceLocation &SL); + bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR, + SourceLocation SL); /// \brief Helper to set loop increment. bool SetStep(Expr *NewStep, bool Subtract); }; @@ -2313,8 +2887,7 @@ bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar, } bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp, - const SourceRange &SR, - const SourceLocation &SL) { + SourceRange SR, SourceLocation SL) { // State consistency checking to ensure correct usage. assert(Var != nullptr && LB != nullptr && UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp); @@ -2410,7 +2983,7 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) { } else if (auto DS = dyn_cast<DeclStmt>(S)) { if (DS->isSingleDecl()) { if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) { - if (Var->hasInit()) { + if (Var->hasInit() && !Var->getType()->isReferenceType()) { // Accept non-canonical init form here but emit ext. warning. if (Var->getInitStyle() != VarDecl::CInit && EmitDiags) SemaRef.Diag(S->getLocStart(), @@ -2630,6 +3203,8 @@ public: NewVD->setPreviousDeclInSameBlockScope( VD->isPreviousDeclInSameBlockScope()); VD->getDeclContext()->addHiddenDecl(NewVD); + if (VD->hasAttrs()) + NewVD->setAttrs(VD->getAttrs()); transformedLocalDecl(VD, NewVD); return NewVD; } @@ -2802,7 +3377,21 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const { /// \brief Build reference expression to the counter be used for codegen. Expr *OpenMPIterationSpaceChecker::BuildCounterVar() const { - return buildDeclRefExpr(SemaRef, Var, Var->getType(), DefaultLoc); + return buildDeclRefExpr(SemaRef, Var, Var->getType().getNonReferenceType(), + DefaultLoc); +} + +Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const { + if (Var && !Var->isInvalidDecl()) { + auto Type = Var->getType().getNonReferenceType(); + auto *PrivateVar = + buildVarDecl(SemaRef, DefaultLoc, Type, Var->getName(), + Var->hasAttrs() ? &Var->getAttrs() : nullptr); + if (PrivateVar->isInvalidDecl()) + return nullptr; + return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc); + } + return nullptr; } /// \brief Build initization of the counter be used for codegen. @@ -2820,6 +3409,8 @@ struct LoopIterationSpace { Expr *NumIterations; /// \brief The loop counter variable. Expr *CounterVar; + /// \brief Private loop counter variable. + Expr *PrivateCounterVar; /// \brief This is initializer for the initial value of #CounterVar. Expr *CounterInit; /// \brief This is step for the #CounterVar used to generate its update: @@ -2840,14 +3431,13 @@ struct LoopIterationSpace { 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 && + unsigned AssociatedLoops = DSAStack->getAssociatedLoops(); + if (AssociatedLoops > 0 && isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { OpenMPIterationSpaceChecker ISC(*this, ForLoc); - if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) { + if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) DSAStack->addLoopControlVariable(ISC.GetLoopVar()); - } - DSAStack->setCollapseNumber(CollapseIteration - 1); + DSAStack->setAssociatedLoops(AssociatedLoops - 1); } } @@ -2856,7 +3446,7 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { static bool CheckOpenMPIterationSpace( OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, - Expr *NestedLoopCountExpr, + Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA, LoopIterationSpace &ResultIterSpace) { // OpenMP [2.6, Canonical Loop Form] @@ -2864,13 +3454,24 @@ static bool CheckOpenMPIterationSpace( auto For = dyn_cast_or_null<ForStmt>(S); if (!For) { SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for) - << (NestedLoopCountExpr != nullptr) << getOpenMPDirectiveName(DKind) - << NestedLoopCount << (CurrentNestedLoopCount > 0) - << CurrentNestedLoopCount; - if (NestedLoopCount > 1) - SemaRef.Diag(NestedLoopCountExpr->getExprLoc(), - diag::note_omp_collapse_expr) - << NestedLoopCountExpr->getSourceRange(); + << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) + << getOpenMPDirectiveName(DKind) << NestedLoopCount + << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; + if (NestedLoopCount > 1) { + if (CollapseLoopCountExpr && OrderedLoopCountExpr) + SemaRef.Diag(DSA.getConstructLoc(), + diag::note_omp_collapse_ordered_expr) + << 2 << CollapseLoopCountExpr->getSourceRange() + << OrderedLoopCountExpr->getSourceRange(); + else if (CollapseLoopCountExpr) + SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), + diag::note_omp_collapse_ordered_expr) + << 0 << CollapseLoopCountExpr->getSourceRange(); + else + SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), + diag::note_omp_collapse_ordered_expr) + << 1 << OrderedLoopCountExpr->getSourceRange(); + } return true; } assert(For->getBody()); @@ -2893,7 +3494,7 @@ static bool CheckOpenMPIterationSpace( // A variable of signed or unsigned integer type. // For C++, a variable of a random access iterator type. // For C, a variable of a pointer type. - auto VarType = Var->getType(); + auto VarType = Var->getType().getNonReferenceType(); if (!VarType->isDependentType() && !VarType->isIntegerType() && !VarType->isPointerType() && !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) { @@ -2929,12 +3530,12 @@ static bool CheckOpenMPIterationSpace( ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate) : OMPC_private; if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && - 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_threadprivate)) && - ((DVar.CKind != OMPC_private && DVar.CKind != OMPC_threadprivate) || - DVar.RefExpr != nullptr)) { + DVar.CKind != PredeterminedCKind) || + ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop || + isOpenMPDistributeDirective(DKind)) && + !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && + DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && + (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(PredeterminedCKind); @@ -2945,7 +3546,8 @@ static bool CheckOpenMPIterationSpace( } 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). + // lastprivate (for simd directives with several collapsed or ordered + // loops). if (DVar.CKind == OMPC_unknown) DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(), /*FromParent=*/false); @@ -2966,8 +3568,11 @@ static bool CheckOpenMPIterationSpace( // Build the loop's iteration space representation. ResultIterSpace.PreCond = ISC.BuildPreCond(DSA.getCurScope(), For->getCond()); ResultIterSpace.NumIterations = ISC.BuildNumIterations( - DSA.getCurScope(), /* LimitedType */ isOpenMPWorksharingDirective(DKind)); + DSA.getCurScope(), (isOpenMPWorksharingDirective(DKind) || + isOpenMPTaskLoopDirective(DKind) || + isOpenMPDistributeDirective(DKind))); ResultIterSpace.CounterVar = ISC.BuildCounterVar(); + ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar(); ResultIterSpace.CounterInit = ISC.BuildCounterInit(); ResultIterSpace.CounterStep = ISC.BuildCounterStep(); ResultIterSpace.InitSrcRange = ISC.GetInitSrcRange(); @@ -2978,6 +3583,7 @@ static bool CheckOpenMPIterationSpace( HasErrors |= (ResultIterSpace.PreCond == nullptr || ResultIterSpace.NumIterations == nullptr || ResultIterSpace.CounterVar == nullptr || + ResultIterSpace.PrivateCounterVar == nullptr || ResultIterSpace.CounterInit == nullptr || ResultIterSpace.CounterStep == nullptr); @@ -3091,17 +3697,33 @@ static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) { /// \return Returns 0 if one of the collapsed stmts is not canonical for loop, /// number of collapsed loops otherwise. static unsigned -CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, - Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, +CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, + Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, + DSAStackTy &DSA, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA, OMPLoopDirective::HelperExprs &Built) { unsigned NestedLoopCount = 1; - if (NestedLoopCountExpr) { + if (CollapseLoopCountExpr) { // Found 'collapse' clause - calculate collapse number. llvm::APSInt Result; - if (NestedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) + if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) NestedLoopCount = Result.getLimitedValue(); } + if (OrderedLoopCountExpr) { + // Found 'ordered' clause - calculate collapse number. + llvm::APSInt Result; + if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { + if (Result.getLimitedValue() < NestedLoopCount) { + SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), + diag::err_omp_wrong_ordered_loop_count) + << OrderedLoopCountExpr->getSourceRange(); + SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), + diag::note_collapse_loop_count) + << CollapseLoopCountExpr->getSourceRange(); + } + NestedLoopCount = Result.getLimitedValue(); + } + } // This is helper routine for loop directives (e.g., 'for', 'simd', // 'for simd', etc.). SmallVector<LoopIterationSpace, 4> IterSpaces; @@ -3109,8 +3731,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true); for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, - NestedLoopCount, NestedLoopCountExpr, - VarsWithImplicitDSA, IterSpaces[Cnt])) + NestedLoopCount, CollapseLoopCountExpr, + OrderedLoopCountExpr, VarsWithImplicitDSA, + IterSpaces[Cnt])) return 0; // Move on to the next nested for loop, or to the loop body. // OpenMP [2.8.1, simd construct, Restrictions] @@ -3127,11 +3750,12 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // An example of what is generated for the following code: // - // #pragma omp simd collapse(2) + // #pragma omp simd collapse(2) ordered(2) // for (i = 0; i < NI; ++i) - // for (j = J0; j < NJ; j+=2) { - // <loop body> - // } + // for (k = 0; k < NK; ++k) + // for (j = J0; j < NJ; j+=2) { + // <loop body> + // } // // We generate the code below. // Note: the loop body may be outlined in CodeGen. @@ -3254,7 +3878,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, QualType VType = LastIteration.get()->getType(); // Build variables passed into runtime, nesessary for worksharing directives. ExprResult LB, UB, IL, ST, EUB; - if (isOpenMPWorksharingDirective(DKind)) { + if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || + isOpenMPDistributeDirective(DKind)) { // Lower bound variable, initialized with zero. VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb"); LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc); @@ -3302,7 +3927,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, { VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.iv"); IV = buildDeclRefExpr(SemaRef, IVDecl, VType, InitLoc); - Expr *RHS = isOpenMPWorksharingDirective(DKind) + Expr *RHS = (isOpenMPWorksharingDirective(DKind) || + isOpenMPTaskLoopDirective(DKind) || + isOpenMPDistributeDirective(DKind)) ? LB.get() : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); @@ -3312,7 +3939,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops. SourceLocation CondLoc; ExprResult Cond = - isOpenMPWorksharingDirective(DKind) + (isOpenMPWorksharingDirective(DKind) || + isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)) ? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()) : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), NumIterations.get()); @@ -3332,7 +3960,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, // Increments for worksharing loops (LB = LB + ST; UB = UB + ST). // Used for directives with static scheduling. ExprResult NextLB, NextUB; - if (isOpenMPWorksharingDirective(DKind)) { + if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || + isOpenMPDistributeDirective(DKind)) { // LB + ST NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get()); if (!NextLB.isUsable()) @@ -3437,6 +4066,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, } // Save results Built.Counters[Cnt] = IS.CounterVar; + Built.PrivateCounters[Cnt] = IS.PrivateCounterVar; Built.Inits[Cnt] = Init.get(); Built.Updates[Cnt] = Update.get(); Built.Finals[Cnt] = Final.get(); @@ -3467,26 +4097,60 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, return NestedLoopCount; } -static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { - auto &&CollapseFilter = [](const OMPClause *C) -> bool { - return C->getClauseKind() == OMPC_collapse; - }; - OMPExecutableDirective::filtered_clause_iterator<decltype(CollapseFilter)> I( - Clauses, std::move(CollapseFilter)); - if (I) - return cast<OMPCollapseClause>(*I)->getNumForLoops(); +static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { + auto CollapseClauses = + OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses); + if (CollapseClauses.begin() != CollapseClauses.end()) + return (*CollapseClauses.begin())->getNumForLoops(); + return nullptr; +} + +static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) { + auto OrderedClauses = + OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses); + if (OrderedClauses.begin() != OrderedClauses.end()) + return (*OrderedClauses.begin())->getNumForLoops(); return nullptr; } +static bool checkSimdlenSafelenValues(Sema &S, const Expr *Simdlen, + const Expr *Safelen) { + llvm::APSInt SimdlenRes, SafelenRes; + if (Simdlen->isValueDependent() || Simdlen->isTypeDependent() || + Simdlen->isInstantiationDependent() || + Simdlen->containsUnexpandedParameterPack()) + return false; + if (Safelen->isValueDependent() || Safelen->isTypeDependent() || + Safelen->isInstantiationDependent() || + Safelen->containsUnexpandedParameterPack()) + return false; + Simdlen->EvaluateAsInt(SimdlenRes, S.Context); + Safelen->EvaluateAsInt(SafelenRes, S.Context); + // OpenMP 4.1 [2.8.1, simd Construct, Restrictions] + // If both simdlen and safelen clauses are specified, the value of the simdlen + // parameter must be less than or equal to the value of the safelen parameter. + if (SimdlenRes > SafelenRes) { + S.Diag(Simdlen->getExprLoc(), diag::err_omp_wrong_simdlen_safelen_values) + << Simdlen->getSourceRange() << Safelen->getSourceRange(); + return true; + } + return false; +} + StmtResult Sema::ActOnOpenMPSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. - unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this, - *DSAStack, VarsWithImplicitDSA, B); + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. + unsigned NestedLoopCount = CheckOpenMPLoop( + OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), + AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); @@ -3503,6 +4167,24 @@ StmtResult Sema::ActOnOpenMPSimdDirective( } } + // OpenMP 4.1 [2.8.1, simd Construct, Restrictions] + // If both simdlen and safelen clauses are specified, the value of the simdlen + // parameter must be less than or equal to the value of the safelen parameter. + OMPSafelenClause *Safelen = nullptr; + OMPSimdlenClause *Simdlen = nullptr; + for (auto *Clause : Clauses) { + if (Clause->getClauseKind() == OMPC_safelen) + Safelen = cast<OMPSafelenClause>(Clause); + else if (Clause->getClauseKind() == OMPC_simdlen) + Simdlen = cast<OMPSimdlenClause>(Clause); + if (Safelen && Simdlen) + break; + } + if (Simdlen && Safelen && + checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), + Safelen->getSafelen())) + return StmtError(); + getCurFunction()->setHasBranchProtectedScope(); return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); @@ -3512,31 +4194,52 @@ StmtResult Sema::ActOnOpenMPForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. - unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this, - *DSAStack, VarsWithImplicitDSA, B); + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. + unsigned NestedLoopCount = CheckOpenMPLoop( + OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), + AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); assert((CurContext->isDependentContext() || B.builtAll()) && "omp for 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 OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, - Clauses, AStmt, B); + Clauses, AStmt, B, DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPForSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_for_simd, GetCollapseNumberExpr(Clauses), AStmt, - *this, *DSAStack, VarsWithImplicitDSA, B); + CheckOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses), + getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); @@ -3553,6 +4256,24 @@ StmtResult Sema::ActOnOpenMPForSimdDirective( } } + // OpenMP 4.1 [2.8.1, simd Construct, Restrictions] + // If both simdlen and safelen clauses are specified, the value of the simdlen + // parameter must be less than or equal to the value of the safelen parameter. + OMPSafelenClause *Safelen = nullptr; + OMPSimdlenClause *Simdlen = nullptr; + for (auto *Clause : Clauses) { + if (Clause->getClauseKind() == OMPC_safelen) + Safelen = cast<OMPSafelenClause>(Clause); + else if (Clause->getClauseKind() == OMPC_simdlen) + Simdlen = cast<OMPSimdlenClause>(Clause); + if (Safelen && Simdlen) + break; + } + if (Simdlen && Safelen && + checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), + Safelen->getSafelen())) + return StmtError(); + getCurFunction()->setHasBranchProtectedScope(); return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); @@ -3562,23 +4283,28 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); auto BaseStmt = AStmt; while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt)) BaseStmt = CS->getCapturedStmt(); if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) { auto S = C->children(); - if (!S) + if (S.begin() == S.end()) return StmtError(); // All associated statements must be '#pragma omp section' except for // the first one. - for (Stmt *SectionStmt : ++S) { + for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) { if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { if (SectionStmt) Diag(SectionStmt->getLocStart(), diag::err_omp_sections_substmt_not_section); return StmtError(); } + cast<OMPSectionDirective>(SectionStmt) + ->setHasCancel(DSAStack->isCancelRegion()); } } else { Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt); @@ -3587,25 +4313,33 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); - return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, - AStmt); + return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, + DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); getCurFunction()->setHasBranchProtectedScope(); + DSAStack->setParentCancelRegion(DSAStack->isCancelRegion()); - return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt); + return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt, + DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); getCurFunction()->setHasBranchProtectedScope(); @@ -3632,30 +4366,81 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); getCurFunction()->setHasBranchProtectedScope(); return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt); } -StmtResult -Sema::ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +StmtResult Sema::ActOnOpenMPCriticalDirective( + const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + + bool ErrorFound = false; + llvm::APSInt Hint; + SourceLocation HintLoc; + bool DependentHint = false; + for (auto *C : Clauses) { + if (C->getClauseKind() == OMPC_hint) { + if (!DirName.getName()) { + Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name); + ErrorFound = true; + } + Expr *E = cast<OMPHintClause>(C)->getHint(); + if (E->isTypeDependent() || E->isValueDependent() || + E->isInstantiationDependent()) + DependentHint = true; + else { + Hint = E->EvaluateKnownConstInt(Context); + HintLoc = C->getLocStart(); + } + } + } + if (ErrorFound) + return StmtError(); + auto Pair = DSAStack->getCriticalWithHint(DirName); + if (Pair.first && DirName.getName() && !DependentHint) { + if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) { + Diag(StartLoc, diag::err_omp_critical_with_hint); + if (HintLoc.isValid()) { + Diag(HintLoc, diag::note_omp_critical_hint_here) + << 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false); + } else + Diag(StartLoc, diag::note_omp_critical_no_hint) << 0; + if (auto *C = Pair.first->getSingleClause<OMPHintClause>()) { + Diag(C->getLocStart(), diag::note_omp_critical_hint_here) + << 1 + << C->getHint()->EvaluateKnownConstInt(Context).toString( + /*Radix=*/10, /*Signed=*/false); + } else + Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1; + } + } getCurFunction()->setHasBranchProtectedScope(); - return OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc, - AStmt); + auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc, + Clauses, AStmt); + if (!Pair.first && DirName.getName() && !DependentHint) + DSAStack->addCriticalWithHint(Dir, Hint); + return Dir; } StmtResult Sema::ActOnOpenMPParallelForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + CapturedStmt *CS = cast<CapturedStmt>(AStmt); // 1.2.2 OpenMP Language Terminology // Structured block - An executable statement with a single entry at the @@ -3665,26 +4450,41 @@ StmtResult Sema::ActOnOpenMPParallelForDirective( CS->getCapturedDecl()->setNothrow(); OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_parallel_for, GetCollapseNumberExpr(Clauses), AStmt, - *this, *DSAStack, VarsWithImplicitDSA, B); + CheckOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses), + getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); assert((CurContext->isDependentContext() || B.builtAll()) && "omp parallel for 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 OMPParallelForDirective::Create(Context, StartLoc, EndLoc, - NestedLoopCount, Clauses, AStmt, B); + NestedLoopCount, Clauses, AStmt, B, + DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPParallelForSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + CapturedStmt *CS = cast<CapturedStmt>(AStmt); // 1.2.2 OpenMP Language Terminology // Structured block - An executable statement with a single entry at the @@ -3694,10 +4494,12 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective( CS->getCapturedDecl()->setNothrow(); OMPLoopDirective::HelperExprs B; - // In presence of clause 'collapse', it will define the nested loops number. + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. unsigned NestedLoopCount = - CheckOpenMPLoop(OMPD_parallel_for_simd, GetCollapseNumberExpr(Clauses), - AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); + CheckOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses), + getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); if (NestedLoopCount == 0) return StmtError(); @@ -3711,6 +4513,24 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective( } } + // OpenMP 4.1 [2.8.1, simd Construct, Restrictions] + // If both simdlen and safelen clauses are specified, the value of the simdlen + // parameter must be less than or equal to the value of the safelen parameter. + OMPSafelenClause *Safelen = nullptr; + OMPSimdlenClause *Simdlen = nullptr; + for (auto *Clause : Clauses) { + if (Clause->getClauseKind() == OMPC_safelen) + Safelen = cast<OMPSafelenClause>(Clause); + else if (Clause->getClauseKind() == OMPC_simdlen) + Simdlen = cast<OMPSimdlenClause>(Clause); + if (Safelen && Simdlen) + break; + } + if (Simdlen && Safelen && + checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), + Safelen->getSafelen())) + return StmtError(); + getCurFunction()->setHasBranchProtectedScope(); return OMPParallelForSimdDirective::Create( Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); @@ -3720,23 +4540,28 @@ StmtResult Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); auto BaseStmt = AStmt; while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt)) BaseStmt = CS->getCapturedStmt(); if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) { auto S = C->children(); - if (!S) + if (S.begin() == S.end()) return StmtError(); // All associated statements must be '#pragma omp section' except for // the first one. - for (Stmt *SectionStmt : ++S) { + for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) { if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { if (SectionStmt) Diag(SectionStmt->getLocStart(), diag::err_omp_parallel_sections_substmt_not_section); return StmtError(); } + cast<OMPSectionDirective>(SectionStmt) + ->setHasCancel(DSAStack->isCancelRegion()); } } else { Diag(AStmt->getLocStart(), @@ -3746,14 +4571,16 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); - return OMPParallelSectionsDirective::Create(Context, StartLoc, EndLoc, - Clauses, AStmt); + return OMPParallelSectionsDirective::Create( + Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + CapturedStmt *CS = cast<CapturedStmt>(AStmt); // 1.2.2 OpenMP Language Terminology // Structured block - An executable statement with a single entry at the @@ -3764,7 +4591,8 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, getCurFunction()->setHasBranchProtectedScope(); - return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); + return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, + DSAStack->isCancelRegion()); } StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, @@ -3785,7 +4613,10 @@ StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc, StmtResult Sema::ActOnOpenMPTaskgroupDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); getCurFunction()->setHasBranchProtectedScope(); @@ -3799,14 +4630,79 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses, return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses); } -StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt, +StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + OMPClause *DependFound = nullptr; + OMPClause *DependSourceClause = nullptr; + OMPClause *DependSinkClause = nullptr; + bool ErrorFound = false; + OMPThreadsClause *TC = nullptr; + OMPSIMDClause *SC = nullptr; + for (auto *C : Clauses) { + if (auto *DC = dyn_cast<OMPDependClause>(C)) { + DependFound = C; + if (DC->getDependencyKind() == OMPC_DEPEND_source) { + if (DependSourceClause) { + Diag(C->getLocStart(), diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(OMPD_ordered) + << getOpenMPClauseName(OMPC_depend) << 2; + ErrorFound = true; + } else + DependSourceClause = C; + if (DependSinkClause) { + Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed) + << 0; + ErrorFound = true; + } + } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) { + if (DependSourceClause) { + Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed) + << 1; + ErrorFound = true; + } + DependSinkClause = C; + } + } else if (C->getClauseKind() == OMPC_threads) + TC = cast<OMPThreadsClause>(C); + else if (C->getClauseKind() == OMPC_simd) + SC = cast<OMPSIMDClause>(C); + } + if (!ErrorFound && !SC && + isOpenMPSimdDirective(DSAStack->getParentDirective())) { + // OpenMP [2.8.1,simd Construct, Restrictions] + // An ordered construct with the simd clause is the only OpenMP construct + // that can appear in the simd region. + Diag(StartLoc, diag::err_omp_prohibited_region_simd); + ErrorFound = true; + } else if (DependFound && (TC || SC)) { + Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd) + << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind()); + ErrorFound = true; + } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) { + Diag(DependFound->getLocStart(), + diag::err_omp_ordered_directive_without_param); + ErrorFound = true; + } else if (TC || Clauses.empty()) { + if (auto *Param = DSAStack->getParentOrderedRegionParam()) { + SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc; + Diag(ErrLoc, diag::err_omp_ordered_directive_with_param) + << (TC != nullptr); + Diag(Param->getLocStart(), diag::note_omp_ordered_param); + ErrorFound = true; + } + } + if ((!AStmt && !DependFound) || ErrorFound) + return StmtError(); - getCurFunction()->setHasBranchProtectedScope(); + if (AStmt) { + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); - return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt); + getCurFunction()->setHasBranchProtectedScope(); + } + + return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); } namespace { @@ -4006,7 +4902,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, NoteLoc = AtomicUnaryOp->getOperatorLoc(); NoteRange = SourceRange(NoteLoc, NoteLoc); } - } else { + } else if (!AtomicBody->isInstantiationDependent()) { ErrorFound = NotABinaryOrUnaryExpression; NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); NoteRange = ErrorRange = AtomicBody->getSourceRange(); @@ -4053,7 +4949,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + auto CS = cast<CapturedStmt>(AStmt); // 1.2.2 OpenMP Language Terminology // Structured block - An executable statement with a single entry at the @@ -4150,7 +5048,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, NoteLoc = NotScalarExpr->getExprLoc(); NoteRange = NotScalarExpr->getSourceRange(); } - } else { + } else if (!AtomicBody->isInstantiationDependent()) { ErrorFound = NotAnAssignmentOp; ErrorLoc = AtomicBody->getExprLoc(); ErrorRange = AtomicBody->getSourceRange(); @@ -4211,7 +5109,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, NoteLoc = NotScalarExpr->getExprLoc(); NoteRange = NotScalarExpr->getSourceRange(); } - } else { + } else if (!AtomicBody->isInstantiationDependent()) { ErrorFound = NotAnAssignmentOp; ErrorLoc = AtomicBody->getExprLoc(); ErrorRange = AtomicBody->getSourceRange(); @@ -4289,7 +5187,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, UE = Checker.getUpdateExpr(); IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); IsPostfixUpdate = Checker.isPostfixUpdate(); - } else { + } else if (!AtomicBody->isInstantiationDependent()) { ErrorLoc = AtomicBody->getExprLoc(); ErrorRange = AtomicBody->getSourceRange(); NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() @@ -4396,46 +5294,54 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } 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) { + auto *FirstExpr = dyn_cast<Expr>(First); + auto *SecondExpr = dyn_cast<Expr>(Second); + if (!FirstExpr || !SecondExpr || + !(FirstExpr->isInstantiationDependent() || + SecondExpr->isInstantiationDependent())) { + auto *FirstBinOp = dyn_cast<BinaryOperator>(First); + if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { ErrorFound = NotAnAssignmentOp; - NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc() - : Second->getLocStart(); - NoteRange = ErrorRange = SecondBinOp - ? SecondBinOp->getSourceRange() + NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() + : First->getLocStart(); + NoteRange = ErrorRange = FirstBinOp + ? FirstBinOp->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; + 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 { - ErrorFound = NotASpecificExpression; - ErrorLoc = FirstBinOp->getExprLoc(); - ErrorRange = FirstBinOp->getSourceRange(); - NoteLoc = SecondBinOp->getLHS()->getExprLoc(); - NoteRange = SecondBinOp->getRHS()->getSourceRange(); + 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(); + } } } } @@ -4474,7 +5380,16 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + + CapturedStmt *CS = cast<CapturedStmt>(AStmt); + // 1.2.2 OpenMP Language Terminology + // Structured block - An executable statement with a single entry at the + // 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. + CS->getCapturedDecl()->setNothrow(); // OpenMP [2.16, Nesting of Regions] // If specified, a teams construct must be contained within a target @@ -4511,10 +5426,27 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); } +StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + + getCurFunction()->setHasBranchProtectedScope(); + + return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses, + AStmt); +} + StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + if (!AStmt) + return StmtError(); + CapturedStmt *CS = cast<CapturedStmt>(AStmt); // 1.2.2 OpenMP Language Terminology // Structured block - An executable statement with a single entry at the @@ -4550,7 +5482,8 @@ Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, CancelRegion); } -StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc, +StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses, + SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) { if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for && @@ -4567,7 +5500,123 @@ StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc, Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1; return StmtError(); } - return OMPCancelDirective::Create(Context, StartLoc, EndLoc, CancelRegion); + DSAStack->setParentCancelRegion(/*Cancel=*/true); + return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses, + CancelRegion); +} + +static bool checkGrainsizeNumTasksClauses(Sema &S, + ArrayRef<OMPClause *> Clauses) { + OMPClause *PrevClause = nullptr; + bool ErrorFound = false; + for (auto *C : Clauses) { + if (C->getClauseKind() == OMPC_grainsize || + C->getClauseKind() == OMPC_num_tasks) { + if (!PrevClause) + PrevClause = C; + else if (PrevClause->getClauseKind() != C->getClauseKind()) { + S.Diag(C->getLocStart(), + diag::err_omp_grainsize_num_tasks_mutually_exclusive) + << getOpenMPClauseName(C->getClauseKind()) + << getOpenMPClauseName(PrevClause->getClauseKind()); + S.Diag(PrevClause->getLocStart(), + diag::note_omp_previous_grainsize_num_tasks) + << getOpenMPClauseName(PrevClause->getClauseKind()); + ErrorFound = true; + } + } + } + return ErrorFound; +} + +StmtResult Sema::ActOnOpenMPTaskLoopDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + OMPLoopDirective::HelperExprs B; + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. + unsigned NestedLoopCount = + CheckOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses), + /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); + if (NestedLoopCount == 0) + return StmtError(); + + assert((CurContext->isDependentContext() || B.builtAll()) && + "omp for loop exprs were not built"); + + // OpenMP, [2.9.2 taskloop Construct, Restrictions] + // The grainsize clause and num_tasks clause are mutually exclusive and may + // not appear on the same taskloop directive. + if (checkGrainsizeNumTasksClauses(*this, Clauses)) + return StmtError(); + + getCurFunction()->setHasBranchProtectedScope(); + return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc, + NestedLoopCount, Clauses, AStmt, B); +} + +StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + OMPLoopDirective::HelperExprs B; + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. + unsigned NestedLoopCount = + CheckOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses), + /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack, + VarsWithImplicitDSA, B); + if (NestedLoopCount == 0) + return StmtError(); + + assert((CurContext->isDependentContext() || B.builtAll()) && + "omp for loop exprs were not built"); + + // OpenMP, [2.9.2 taskloop Construct, Restrictions] + // The grainsize clause and num_tasks clause are mutually exclusive and may + // not appear on the same taskloop directive. + if (checkGrainsizeNumTasksClauses(*this, Clauses)) + return StmtError(); + + getCurFunction()->setHasBranchProtectedScope(); + return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc, + NestedLoopCount, Clauses, AStmt, B); +} + +StmtResult Sema::ActOnOpenMPDistributeDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + OMPLoopDirective::HelperExprs B; + // In presence of clause 'collapse' with number of loops, it will + // define the nested loops number. + unsigned NestedLoopCount = + CheckOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses), + nullptr /*ordered not a clause on distribute*/, AStmt, + *this, *DSAStack, VarsWithImplicitDSA, B); + if (NestedLoopCount == 0) + return StmtError(); + + assert((CurContext->isDependentContext() || B.builtAll()) && + "omp for loop exprs were not built"); + + getCurFunction()->setHasBranchProtectedScope(); + return OMPDistributeDirective::Create(Context, StartLoc, EndLoc, + NestedLoopCount, Clauses, AStmt, B); } OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, @@ -4576,9 +5625,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation EndLoc) { OMPClause *Res = nullptr; switch (Kind) { - case OMPC_if: - Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc); - break; case OMPC_final: Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc); break; @@ -4588,9 +5634,37 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_safelen: Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_simdlen: + Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc); + break; case OMPC_collapse: Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_ordered: + Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr); + break; + case OMPC_device: + Res = ActOnOpenMPDeviceClause(Expr, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_num_teams: + Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_thread_limit: + Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_priority: + Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_grainsize: + Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_num_tasks: + Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_hint: + Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_if: case OMPC_default: case OMPC_proc_bind: case OMPC_schedule: @@ -4603,7 +5677,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_aligned: case OMPC_copyin: case OMPC_copyprivate: - case OMPC_ordered: case OMPC_nowait: case OMPC_untied: case OMPC_mergeable: @@ -4615,14 +5688,21 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_capture: case OMPC_seq_cst: case OMPC_depend: + case OMPC_threads: + case OMPC_simd: + case OMPC_map: + case OMPC_nogroup: case OMPC_unknown: llvm_unreachable("Clause is not allowed."); } return Res; } -OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc, +OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, + Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation NameModifierLoc, + SourceLocation ColonLoc, SourceLocation EndLoc) { Expr *ValExpr = Condition; if (!Condition->isValueDependent() && !Condition->isTypeDependent() && @@ -4636,7 +5716,8 @@ OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc, ValExpr = Val.get(); } - return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc); + return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc, + NameModifierLoc, ColonLoc, EndLoc); } OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition, @@ -4701,38 +5782,52 @@ ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc, return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser); } +static bool IsNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, + OpenMPClauseKind CKind, + bool StrictlyPositive) { + if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() && + !ValExpr->isInstantiationDependent()) { + SourceLocation Loc = ValExpr->getExprLoc(); + ExprResult Value = + SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr); + if (Value.isInvalid()) + return false; + + ValExpr = Value.get(); + // The expression must evaluate to a non-negative integer value. + llvm::APSInt Result; + if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) && + Result.isSigned() && + !((!StrictlyPositive && Result.isNonNegative()) || + (StrictlyPositive && Result.isStrictlyPositive()))) { + SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) + << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) + << ValExpr->getSourceRange(); + return false; + } + } + return true; +} + OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { Expr *ValExpr = NumThreads; - if (!NumThreads->isValueDependent() && !NumThreads->isTypeDependent() && - !NumThreads->containsUnexpandedParameterPack()) { - SourceLocation NumThreadsLoc = NumThreads->getLocStart(); - ExprResult Val = - PerformOpenMPImplicitIntegerConversion(NumThreadsLoc, NumThreads); - if (Val.isInvalid()) - return nullptr; - ValExpr = Val.get(); - - // OpenMP [2.5, Restrictions] - // The num_threads expression must evaluate to a positive integer value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, Context) && Result.isSigned() && - !Result.isStrictlyPositive()) { - Diag(NumThreadsLoc, diag::err_omp_negative_expression_in_clause) - << "num_threads" << NumThreads->getSourceRange(); - return nullptr; - } - } + // OpenMP [2.5, Restrictions] + // The num_threads expression must evaluate to a positive integer value. + if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads, + /*StrictlyPositive=*/true)) + return nullptr; return new (Context) OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc, EndLoc); } ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, - OpenMPClauseKind CKind) { + OpenMPClauseKind CKind, + bool StrictlyPositive) { if (!E) return ExprError(); if (E->isValueDependent() || E->isTypeDependent() || @@ -4742,9 +5837,11 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, ExprResult ICE = VerifyIntegerConstantExpression(E, &Result); if (ICE.isInvalid()) return ExprError(); - if (!Result.isStrictlyPositive()) { + if ((StrictlyPositive && !Result.isStrictlyPositive()) || + (!StrictlyPositive && !Result.isNonNegative())) { Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause) - << getOpenMPClauseName(CKind) << E->getSourceRange(); + << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) + << E->getSourceRange(); return ExprError(); } if (CKind == OMPC_aligned && !Result.isPowerOf2()) { @@ -4752,9 +5849,10 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, << E->getSourceRange(); return ExprError(); } - if (CKind == OMPC_collapse) { - DSAStack->setCollapseNumber(Result.getExtValue()); - } + if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1) + DSAStack->setAssociatedLoops(Result.getExtValue()); + else if (CKind == OMPC_ordered) + DSAStack->setAssociatedLoops(Result.getExtValue()); return ICE; } @@ -4771,6 +5869,19 @@ OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc, OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + // OpenMP [2.8.1, simd construct, Description] + // The parameter of the simdlen clause must be a constant + // positive integer expression. + ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen); + if (Simdlen.isInvalid()) + return nullptr; + return new (Context) + OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -4788,6 +5899,28 @@ OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops, OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, + SourceLocation EndLoc, + SourceLocation LParenLoc, + Expr *NumForLoops) { + // OpenMP [2.7.1, loop construct, Description] + // OpenMP [2.8.1, simd construct, Description] + // OpenMP [2.9.6, distribute construct, Description] + // The parameter of the ordered clause must be a constant + // positive integer expression if any. + if (NumForLoops && LParenLoc.isValid()) { + ExprResult NumForLoopsResult = + VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered); + if (NumForLoopsResult.isInvalid()) + return nullptr; + NumForLoops = NumForLoopsResult.get(); + } else + NumForLoops = nullptr; + DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops); + return new (Context) + OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPSimpleClause( OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { @@ -4807,6 +5940,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_final: case OMPC_num_threads: case OMPC_safelen: + case OMPC_simdlen: case OMPC_collapse: case OMPC_schedule: case OMPC_private: @@ -4830,39 +5964,58 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_capture: case OMPC_seq_cst: case OMPC_depend: + case OMPC_device: + case OMPC_threads: + case OMPC_simd: + case OMPC_map: + case OMPC_num_teams: + case OMPC_thread_limit: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_nogroup: + case OMPC_num_tasks: + case OMPC_hint: case OMPC_unknown: llvm_unreachable("Clause is not allowed."); } return Res; } +static std::string +getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, + ArrayRef<unsigned> Exclude = llvm::None) { + std::string Values; + unsigned Bound = Last >= 2 ? Last - 2 : 0; + unsigned Skipped = Exclude.size(); + auto S = Exclude.begin(), E = Exclude.end(); + for (unsigned i = First; i < Last; ++i) { + if (std::find(S, E, i) != E) { + --Skipped; + continue; + } + Values += "'"; + Values += getOpenMPSimpleClauseTypeName(K, i); + Values += "'"; + if (i == Bound - Skipped) + Values += " or "; + else if (i != Bound + 1 - Skipped) + Values += ", "; + } + return Values; +} + OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind, SourceLocation KindKwLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { if (Kind == OMPC_DEFAULT_unknown) { - std::string Values; static_assert(OMPC_DEFAULT_unknown > 0, "OMPC_DEFAULT_unknown not greater than 0"); - std::string Sep(", "); - for (unsigned i = 0; i < OMPC_DEFAULT_unknown; ++i) { - Values += "'"; - Values += getOpenMPSimpleClauseTypeName(OMPC_default, i); - Values += "'"; - switch (i) { - case OMPC_DEFAULT_unknown - 2: - Values += " or "; - break; - case OMPC_DEFAULT_unknown - 1: - break; - default: - Values += Sep; - break; - } - } Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) - << Values << getOpenMPClauseName(OMPC_default); + << getListOfPossibleValues(OMPC_default, /*First=*/0, + /*Last=*/OMPC_DEFAULT_unknown) + << getOpenMPClauseName(OMPC_default); return nullptr; } switch (Kind) { @@ -4886,25 +6039,10 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind, SourceLocation LParenLoc, SourceLocation EndLoc) { if (Kind == OMPC_PROC_BIND_unknown) { - std::string Values; - std::string Sep(", "); - for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) { - Values += "'"; - Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i); - Values += "'"; - switch (i) { - case OMPC_PROC_BIND_unknown - 2: - Values += " or "; - break; - case OMPC_PROC_BIND_unknown - 1: - break; - default: - Values += Sep; - break; - } - } Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) - << Values << getOpenMPClauseName(OMPC_proc_bind); + << getListOfPossibleValues(OMPC_proc_bind, /*First=*/0, + /*Last=*/OMPC_PROC_BIND_unknown) + << getOpenMPClauseName(OMPC_proc_bind); return nullptr; } return new (Context) @@ -4912,21 +6050,33 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind, } OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( - OpenMPClauseKind Kind, unsigned Argument, Expr *Expr, + OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ArgumentLoc, SourceLocation CommaLoc, + ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc, SourceLocation EndLoc) { OMPClause *Res = nullptr; switch (Kind) { case OMPC_schedule: + enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; + assert(Argument.size() == NumberOfElements && + ArgumentLoc.size() == NumberOfElements); Res = ActOnOpenMPScheduleClause( - static_cast<OpenMPScheduleClauseKind>(Argument), Expr, StartLoc, - LParenLoc, ArgumentLoc, CommaLoc, EndLoc); + static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]), + static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]), + static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr, + StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2], + ArgumentLoc[ScheduleKind], DelimLoc, EndLoc); break; case OMPC_if: + assert(Argument.size() == 1 && ArgumentLoc.size() == 1); + Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()), + Expr, StartLoc, LParenLoc, ArgumentLoc.back(), + DelimLoc, EndLoc); + break; case OMPC_final: case OMPC_num_threads: case OMPC_safelen: + case OMPC_simdlen: case OMPC_collapse: case OMPC_default: case OMPC_proc_bind: @@ -4951,38 +6101,91 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_capture: case OMPC_seq_cst: case OMPC_depend: + case OMPC_device: + case OMPC_threads: + case OMPC_simd: + case OMPC_map: + case OMPC_num_teams: + case OMPC_thread_limit: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_nogroup: + case OMPC_num_tasks: + case OMPC_hint: case OMPC_unknown: llvm_unreachable("Clause is not allowed."); } return Res; } +static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, + OpenMPScheduleClauseModifier M2, + SourceLocation M1Loc, SourceLocation M2Loc) { + if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) { + SmallVector<unsigned, 2> Excluded; + if (M2 != OMPC_SCHEDULE_MODIFIER_unknown) + Excluded.push_back(M2); + if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) + Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic); + if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic) + Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic); + S.Diag(M1Loc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_schedule, + /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1, + /*Last=*/OMPC_SCHEDULE_MODIFIER_last, + Excluded) + << getOpenMPClauseName(OMPC_schedule); + return true; + } + return false; +} + OMPClause *Sema::ActOnOpenMPScheduleClause( + OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, - SourceLocation EndLoc) { + SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, + SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) { + if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) || + checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc)) + return nullptr; + // OpenMP, 2.7.1, Loop Construct, Restrictions + // Either the monotonic modifier or the nonmonotonic modifier can be specified + // but not both. + if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) || + (M1 == OMPC_SCHEDULE_MODIFIER_monotonic && + M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) || + (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic && + M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) { + Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier) + << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2) + << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1); + return nullptr; + } if (Kind == OMPC_SCHEDULE_unknown) { std::string Values; - std::string Sep(", "); - for (unsigned i = 0; i < OMPC_SCHEDULE_unknown; ++i) { - Values += "'"; - Values += getOpenMPSimpleClauseTypeName(OMPC_schedule, i); - Values += "'"; - switch (i) { - case OMPC_SCHEDULE_unknown - 2: - Values += " or "; - break; - case OMPC_SCHEDULE_unknown - 1: - break; - default: - Values += Sep; - break; - } + if (M1Loc.isInvalid() && M2Loc.isInvalid()) { + unsigned Exclude[] = {OMPC_SCHEDULE_unknown}; + Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, + /*Last=*/OMPC_SCHEDULE_MODIFIER_last, + Exclude); + } else { + Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, + /*Last=*/OMPC_SCHEDULE_unknown); } Diag(KindLoc, diag::err_omp_unexpected_clause_value) << Values << getOpenMPClauseName(OMPC_schedule); return nullptr; } + // OpenMP, 2.7.1, Loop Construct, Restrictions + // The nonmonotonic modifier can only be specified with schedule(dynamic) or + // schedule(guided). + if ((M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic || + M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) && + Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) { + Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc, + diag::err_omp_schedule_nonmonotonic_static); + return nullptr; + } Expr *ValExpr = ChunkSize; Expr *HelperValExpr = nullptr; if (ChunkSize) { @@ -5004,7 +6207,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( if (ValExpr->isIntegerConstantExpr(Result, Context)) { if (Result.isSigned() && !Result.isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) - << "schedule" << ChunkSize->getSourceRange(); + << "schedule" << 1 << ChunkSize->getSourceRange(); return nullptr; } } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { @@ -5018,8 +6221,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( } } - return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, - EndLoc, Kind, ValExpr, HelperValExpr); + return new (Context) + OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind, + ValExpr, HelperValExpr, M1, M1Loc, M2, M2Loc); } OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, @@ -5054,10 +6258,20 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_seq_cst: Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc); break; + case OMPC_threads: + Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc); + break; + case OMPC_simd: + Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc); + break; + case OMPC_nogroup: + Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: case OMPC_safelen: + case OMPC_simdlen: case OMPC_collapse: case OMPC_schedule: case OMPC_private: @@ -5074,18 +6288,20 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_threadprivate: case OMPC_flush: case OMPC_depend: + case OMPC_device: + case OMPC_map: + case OMPC_num_teams: + case OMPC_thread_limit: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_num_tasks: + case OMPC_hint: case OMPC_unknown: llvm_unreachable("Clause is not allowed."); } return Res; } -OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, - SourceLocation EndLoc) { - DSAStack->setOrderedRegion(); - return new (Context) OMPOrderedClause(StartLoc, EndLoc); -} - OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc) { DSAStack->setNowaitRegion(); @@ -5127,12 +6343,28 @@ OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc, return new (Context) OMPSeqCstClause(StartLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPThreadsClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPSIMDClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPNogroupClause(StartLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPVarListClause( OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind, - SourceLocation DepLoc) { + OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier, + OpenMPMapClauseKind MapType, SourceLocation DepLinMapLoc) { OMPClause *Res = nullptr; switch (Kind) { case OMPC_private: @@ -5153,7 +6385,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause( break; case OMPC_linear: Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc, - ColonLoc, EndLoc); + LinKind, DepLinMapLoc, ColonLoc, EndLoc); break; case OMPC_aligned: Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc, @@ -5169,13 +6401,18 @@ OMPClause *Sema::ActOnOpenMPVarListClause( Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc); break; case OMPC_depend: - Res = ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList, StartLoc, - LParenLoc, EndLoc); + Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList, + StartLoc, LParenLoc, EndLoc); + break; + case OMPC_map: + Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, DepLinMapLoc, ColonLoc, + VarList, StartLoc, LParenLoc, EndLoc); break; case OMPC_if: case OMPC_final: case OMPC_num_threads: case OMPC_safelen: + case OMPC_simdlen: case OMPC_collapse: case OMPC_default: case OMPC_proc_bind: @@ -5190,6 +6427,16 @@ OMPClause *Sema::ActOnOpenMPVarListClause( case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_device: + case OMPC_threads: + case OMPC_simd: + case OMPC_num_teams: + case OMPC_thread_limit: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_nogroup: + case OMPC_num_tasks: + case OMPC_hint: case OMPC_unknown: llvm_unreachable("Clause is not allowed."); } @@ -5240,16 +6487,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, diag::err_omp_private_incomplete_type)) { continue; } - if (Type->isReferenceType()) { - Diag(ELoc, diag::err_omp_clause_ref_type_arg) - << getOpenMPClauseName(OMPC_private) << Type; - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - continue; - } + Type = Type.getNonReferenceType(); // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] @@ -5290,7 +6528,8 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, // IdResolver, so the code in the OpenMP region uses original variable for // proper diagnostics. Type = Type.getUnqualifiedType(); - auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName()); + auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName(), + VD->hasAttrs() ? &VD->getAttrs() : nullptr); ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); if (VDPrivate->isInvalidDecl()) continue; @@ -5384,23 +6623,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, diag::err_omp_firstprivate_incomplete_type)) { continue; } - if (Type->isReferenceType()) { - if (IsImplicitClause) { - Diag(ImplicitClauseLoc, - diag::err_omp_task_predetermined_firstprivate_ref_type_arg) - << Type; - Diag(RefExpr->getExprLoc(), diag::note_used_here); - } else { - Diag(ELoc, diag::err_omp_clause_ref_type_arg) - << getOpenMPClauseName(OMPC_firstprivate) << Type; - } - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - continue; - } + Type = Type.getNonReferenceType(); // OpenMP [2.9.3.4, Restrictions, C/C++, p.1] // A variable of class type (or array thereof) that appears in a private @@ -5492,6 +6715,49 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, continue; } } + + // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] + // A list item that is private within a teams region must not appear in a + // firstprivate clause on a distribute construct if any of the distribute + // regions arising from the distribute construct ever bind to any of the + // teams regions arising from the teams construct. + // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] + // A list item that appears in a reduction clause of a teams construct + // must not appear in a firstprivate clause on a distribute construct if + // any of the distribute regions arising from the distribute construct + // ever bind to any of the teams regions arising from the teams construct. + // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] + // A list item may appear in a firstprivate or lastprivate clause but not + // both. + if (CurrDir == OMPD_distribute) { + DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_private), + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPTeamsDirective(K); + }, + false); + if (DVar.CKind == OMPC_private && isOpenMPTeamsDirective(DVar.DKind)) { + Diag(ELoc, diag::err_omp_firstprivate_distribute_private_teams); + ReportOriginalDSA(*this, DSAStack, VD, DVar); + continue; + } + DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction), + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPTeamsDirective(K); + }, + false); + if (DVar.CKind == OMPC_reduction && + isOpenMPTeamsDirective(DVar.DKind)) { + Diag(ELoc, diag::err_omp_firstprivate_distribute_in_teams_reduction); + ReportOriginalDSA(*this, DSAStack, VD, DVar); + continue; + } + DVar = DSAStack->getTopDSA(VD, false); + if (DVar.CKind == OMPC_lastprivate) { + Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute); + ReportOriginalDSA(*this, DSAStack, VD, DVar); + continue; + } + } } // Variably modified types are not supported for tasks. @@ -5509,7 +6775,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, } Type = Type.getUnqualifiedType(); - auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName()); + auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName(), + VD->hasAttrs() ? &VD->getAttrs() : nullptr); // 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 @@ -5536,6 +6803,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, VDPrivate->setInvalidDecl(); else VDPrivate->setInit(Result.getAs<Expr>()); + // Remove temp variable declaration. + Context.Deallocate(VDInitTemp); } else { auto *VDInit = buildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp"); @@ -5618,16 +6887,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, diag::err_omp_lastprivate_incomplete_type)) { continue; } - if (Type->isReferenceType()) { - Diag(ELoc, diag::err_omp_clause_ref_type_arg) - << getOpenMPClauseName(OMPC_lastprivate) << Type; - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - continue; - } + Type = Type.getNonReferenceType(); // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] @@ -5674,11 +6934,13 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, // operator for the class type. Type = Context.getBaseElementType(Type).getNonReferenceType(); auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), - Type.getUnqualifiedType(), ".lastprivate.src"); + Type.getUnqualifiedType(), ".lastprivate.src", + VD->hasAttrs() ? &VD->getAttrs() : nullptr); auto *PseudoSrcExpr = buildDeclRefExpr( *this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc()); auto *DstVD = - buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst"); + buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst", + VD->hasAttrs() ? &VD->getAttrs() : nullptr); auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc()); // For arrays generate assignment operation for single element and replace @@ -5692,6 +6954,18 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, if (AssignmentOp.isInvalid()) continue; + // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] + // A list item may appear in a firstprivate or lastprivate clause but not + // both. + if (CurrDir == OMPD_distribute) { + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); + if (DVar.CKind == OMPC_firstprivate) { + Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute); + ReportOriginalDSA(*this, DSAStack, VD, DVar); + continue; + } + } + if (TopDVar.CKind != OMPC_firstprivate) DSAStack->addDSA(VD, DE, OMPC_lastprivate); Vars.push_back(DE); @@ -5879,6 +7153,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause( case OO_Call: case OO_Subscript: case OO_Conditional: + case OO_Coawait: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("Unexpected reduction identifier"); case OO_None: @@ -5903,6 +7178,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause( } SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> Privates; SmallVector<Expr *, 8> LHSs; SmallVector<Expr *, 8> RHSs; SmallVector<Expr *, 8> ReductionOps; @@ -5911,6 +7187,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause( if (isa<DependentScopeDeclRefExpr>(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + Privates.push_back(nullptr); LHSs.push_back(nullptr); RHSs.push_back(nullptr); ReductionOps.push_back(nullptr); @@ -5922,6 +7199,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause( RefExpr->containsUnexpandedParameterPack()) { // It will be analyzed later. Vars.push_back(RefExpr); + Privates.push_back(nullptr); LHSs.push_back(nullptr); RHSs.push_back(nullptr); ReductionOps.push_back(nullptr); @@ -5937,14 +7215,53 @@ OMPClause *Sema::ActOnOpenMPReductionClause( // OpenMP [2.14.3.3, Restrictions, p.1] // A variable that is part of another variable (as an array or // structure element) cannot appear in a private clause. - auto DE = dyn_cast<DeclRefExpr>(RefExpr); - if (!DE || !isa<VarDecl>(DE->getDecl())) { - Diag(ELoc, diag::err_omp_expected_var_name) << ERange; + auto *DE = dyn_cast<DeclRefExpr>(RefExpr); + auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr); + auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr); + if (!ASE && !OASE && (!DE || !isa<VarDecl>(DE->getDecl()))) { + Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) << ERange; continue; } - auto D = DE->getDecl(); - auto VD = cast<VarDecl>(D); - auto Type = VD->getType(); + QualType Type; + VarDecl *VD = nullptr; + if (DE) { + auto D = DE->getDecl(); + VD = cast<VarDecl>(D); + Type = VD->getType(); + } else if (ASE) { + Type = ASE->getType(); + auto *Base = ASE->getBase()->IgnoreParenImpCasts(); + while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) + Base = TempASE->getBase()->IgnoreParenImpCasts(); + DE = dyn_cast<DeclRefExpr>(Base); + if (DE) + VD = dyn_cast<VarDecl>(DE->getDecl()); + if (!VD) { + Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name) + << 0 << Base->getSourceRange(); + continue; + } + } else if (OASE) { + auto BaseType = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); + if (auto *ATy = BaseType->getAsArrayTypeUnsafe()) + Type = ATy->getElementType(); + else + Type = BaseType->getPointeeType(); + auto *Base = OASE->getBase()->IgnoreParenImpCasts(); + while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) + Base = TempOASE->getBase()->IgnoreParenImpCasts(); + while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) + Base = TempASE->getBase()->IgnoreParenImpCasts(); + DE = dyn_cast<DeclRefExpr>(Base); + if (DE) + VD = dyn_cast<VarDecl>(DE->getDecl()); + if (!VD) { + Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name) + << 1 << Base->getSourceRange(); + continue; + } + } + // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] // A variable that appears in a private clause must not have an incomplete // type or a reference type. @@ -5955,36 +7272,42 @@ OMPClause *Sema::ActOnOpenMPReductionClause( // Arrays may not appear in a reduction clause. if (Type.getNonReferenceType()->isArrayType()) { Diag(ELoc, diag::err_omp_reduction_type_array) << Type << ERange; - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; + if (!ASE && !OASE) { + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + } continue; } // OpenMP [2.14.3.6, reduction clause, Restrictions] // A list item that appears in a reduction clause must not be // const-qualified. if (Type.getNonReferenceType().isConstant(Context)) { - Diag(ELoc, diag::err_omp_const_variable) + Diag(ELoc, diag::err_omp_const_reduction_list_item) << getOpenMPClauseName(OMPC_reduction) << Type << ERange; - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; + if (!ASE && !OASE) { + 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.6, Restrictions, C/C++, p.4] // If a list-item is a reference type then it must bind to the same object // for all threads of the team. - VarDecl *VDDef = VD->getDefinition(); - if (Type->isReferenceType() && VDDef) { - DSARefChecker Check(DSAStack); - if (Check.Visit(VDDef->getInit())) { - Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange; - Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; - continue; + if (!ASE && !OASE) { + VarDecl *VDDef = VD->getDefinition(); + if (Type->isReferenceType() && VDDef) { + DSARefChecker Check(DSAStack); + if (Check.Visit(VDDef->getInit())) { + Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange; + Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; + continue; + } } } // OpenMP [2.14.3.6, reduction clause, Restrictions] @@ -6000,21 +7323,25 @@ OMPClause *Sema::ActOnOpenMPReductionClause( (getLangOpts().CPlusPlus && Type->isArithmeticType()))) { Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg) << getLangOpts().CPlusPlus; - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; + if (!ASE && !OASE) { + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + } continue; } if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) && !getLangOpts().CPlusPlus && Type->isFloatingType()) { Diag(ELoc, diag::err_omp_clause_floating_type_arg); - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; + if (!ASE && !OASE) { + 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 @@ -6028,7 +7355,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause( // Any number of reduction clauses can be specified on the directive, // but a list item can appear only once in the reduction clauses for that // directive. - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); + DSAStackTy::DSAVarData DVar; + DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind == OMPC_reduction) { Diag(ELoc, diag::err_omp_once_referenced) << getOpenMPClauseName(OMPC_reduction); @@ -6059,9 +7387,27 @@ OMPClause *Sema::ActOnOpenMPReductionClause( continue; } } + Type = Type.getNonLValueExprType(Context).getUnqualifiedType(); - auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs"); - auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName()); + auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs", + VD->hasAttrs() ? &VD->getAttrs() : nullptr); + auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName(), + VD->hasAttrs() ? &VD->getAttrs() : nullptr); + auto PrivateTy = Type; + if (OASE) { + // For array sections only: + // Create pseudo array type for private copy. The size for this array will + // be generated during codegen. + // For array subscripts or single variables Private Ty is the same as Type + // (type of the variable or single array element). + PrivateTy = Context.getVariableArrayType( + Type, new (Context) OpaqueValueExpr(SourceLocation(), + Context.getSizeType(), VK_RValue), + ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange()); + } + // Private copy. + auto *PrivateVD = buildVarDecl(*this, ELoc, PrivateTy, VD->getName(), + VD->hasAttrs() ? &VD->getAttrs() : nullptr); // Add initializer for private variable. Expr *Init = nullptr; switch (BOK) { @@ -6170,21 +7516,27 @@ OMPClause *Sema::ActOnOpenMPReductionClause( if (Init) { AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false, /*TypeMayContainAuto=*/false); - } else { + } 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; + if (VD) { + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + } continue; } + // Store initializer for single element in private copy. Will be used during + // codegen. + PrivateVD->setInit(RHSVD->getInit()); + PrivateVD->setInitStyle(RHSVD->getInitStyle()); auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc); auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc); + auto *PrivateDRE = buildDeclRefExpr(*this, PrivateVD, PrivateTy, ELoc); ExprResult ReductionOp = BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK, LHSDRE, RHSDRE); @@ -6201,15 +7553,14 @@ OMPClause *Sema::ActOnOpenMPReductionClause( BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BO_Assign, LHSDRE, ConditionalOp); } - if (ReductionOp.isUsable()) { - ReductionOp = ActOnFinishFullExpr(ReductionOp.get()); - } + ReductionOp = ActOnFinishFullExpr(ReductionOp.get()); } if (ReductionOp.isInvalid()) continue; DSAStack->addDSA(VD, DE, OMPC_reduction); - Vars.push_back(DE); + Vars.push_back(RefExpr); + Privates.push_back(PrivateDRE); LHSs.push_back(LHSDRE); RHSs.push_back(RHSDRE); ReductionOps.push_back(ReductionOp.get()); @@ -6220,22 +7571,28 @@ OMPClause *Sema::ActOnOpenMPReductionClause( return OMPReductionClause::Create( Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars, - ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, LHSs, - RHSs, ReductionOps); + ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates, + LHSs, RHSs, ReductionOps); } -OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ColonLoc, - SourceLocation EndLoc) { +OMPClause *Sema::ActOnOpenMPLinearClause( + ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc, + SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, + SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> Privates; SmallVector<Expr *, 8> Inits; + if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) || + LinKind == OMPC_LINEAR_unknown) { + Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus; + LinKind = OMPC_LINEAR_val; + } 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); + Privates.push_back(nullptr); Inits.push_back(nullptr); continue; } @@ -6278,6 +7635,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, if (QType->isDependentType() || QType->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); + Privates.push_back(nullptr); Inits.push_back(nullptr); continue; } @@ -6287,16 +7645,13 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, diag::err_omp_linear_incomplete_type)) { continue; } - if (QType->isReferenceType()) { - Diag(ELoc, diag::err_omp_clause_ref_type_arg) - << getOpenMPClauseName(OMPC_linear) << QType; - bool IsDecl = - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; + if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) && + !QType->isReferenceType()) { + Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference) + << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind); continue; } + QType = QType.getNonReferenceType(); // A list item must not be const-qualified. if (QType.isConstant(Context)) { @@ -6324,14 +7679,25 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, continue; } + // Build private copy of original var. + auto *Private = buildVarDecl(*this, ELoc, QType, VD->getName(), + VD->hasAttrs() ? &VD->getAttrs() : nullptr); + auto *PrivateRef = buildDeclRefExpr( + *this, Private, DE->getType().getUnqualifiedType(), DE->getExprLoc()); // Build var to save initial value. VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start"); - AddInitializerToDecl(Init, DefaultLvalueConversion(DE).get(), + Expr *InitExpr; + if (LinKind == OMPC_LINEAR_uval) + InitExpr = VD->getInit(); + else + InitExpr = DE; + AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).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); + Privates.push_back(PrivateRef); Inits.push_back(InitRef); } @@ -6356,6 +7722,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); ExprResult CalcStep = BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); + CalcStep = ActOnFinishFullExpr(CalcStep.get()); // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). @@ -6371,8 +7738,9 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, } } - return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc, - Vars, Inits, StepExpr, CalcStepExpr); + return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc, + ColonLoc, EndLoc, Vars, Privates, Inits, + StepExpr, CalcStepExpr); } static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, @@ -6391,27 +7759,35 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Step = cast<BinaryOperator>(CalcStep)->getLHS(); bool HasErrors = false; auto CurInit = Clause.inits().begin(); + auto CurPrivate = Clause.privates().begin(); + auto LinKind = Clause.getModifier(); 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); + Expr *CapturedRef; + if (LinKind == OMPC_LINEAR_uval) + CapturedRef = cast<VarDecl>(DE->getDecl())->getInit(); + else + CapturedRef = + 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, + BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step, /* Subtract */ false); - Update = SemaRef.ActOnFinishFullExpr(Update.get()); + Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(), + /*DiscardedValue=*/true); // Build final: Var = InitExpr + NumIterations * Step ExprResult Final = - BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef, + BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef, InitExpr, NumIterations, Step, /* Subtract */ false); - Final = SemaRef.ActOnFinishFullExpr(Final.get()); + Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(), + /*DiscardedValue=*/true); if (!Update.isUsable() || !Final.isUsable()) { Updates.push_back(nullptr); Finals.push_back(nullptr); @@ -6420,7 +7796,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Updates.push_back(Update.get()); Finals.push_back(Final.get()); } - ++CurInit; + ++CurInit, ++CurPrivate; } Clause.setUpdates(Updates); Clause.setFinals(Finals); @@ -6557,12 +7933,14 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, // copyin clause requires an accessible, unambiguous copy assignment // operator for the class type. auto ElemType = Context.getBaseElementType(Type).getNonReferenceType(); - auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), - ElemType.getUnqualifiedType(), ".copyin.src"); + auto *SrcVD = + buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(), + ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr); auto *PseudoSrcExpr = buildDeclRefExpr( *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc()); auto *DstVD = - buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst"); + buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst", + VD->hasAttrs() ? &VD->getAttrs() : nullptr); auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc()); // For arrays generate assignment operation for single element and replace @@ -6679,13 +8057,16 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(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).getUnqualifiedType(); + Type = Context.getBaseElementType(Type.getNonReferenceType()) + .getUnqualifiedType(); auto *SrcVD = - buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src"); + buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src", + VD->hasAttrs() ? &VD->getAttrs() : nullptr); auto *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, DE->getExprLoc()); auto *DstVD = - buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst"); + buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst", + VD->hasAttrs() ? &VD->getAttrs() : nullptr); auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc()); auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, @@ -6727,61 +8108,430 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { - if (DepKind == OMPC_DEPEND_unknown) { - std::string Values; - std::string Sep(", "); - for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) { - Values += "'"; - Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i); - Values += "'"; - switch (i) { - case OMPC_DEPEND_unknown - 2: - Values += " or "; - break; - case OMPC_DEPEND_unknown - 1: - break; - default: - Values += Sep; - break; - } - } + if (DSAStack->getCurrentDirective() == OMPD_ordered && + DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) { + Diag(DepLoc, diag::err_omp_unexpected_clause_value) + << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend); + return nullptr; + } + if (DSAStack->getCurrentDirective() != OMPD_ordered && + (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source || + DepKind == OMPC_DEPEND_sink)) { + unsigned Except[] = {OMPC_DEPEND_source, OMPC_DEPEND_sink}; Diag(DepLoc, diag::err_omp_unexpected_clause_value) - << Values << getOpenMPClauseName(OMPC_depend); + << getListOfPossibleValues(OMPC_depend, /*First=*/0, + /*Last=*/OMPC_DEPEND_unknown, Except) + << getOpenMPClauseName(OMPC_depend); return nullptr; } SmallVector<Expr *, 8> Vars; - for (auto &RefExpr : VarList) { - assert(RefExpr && "NULL expr in OpenMP shared clause."); - if (isa<DependentScopeDeclRefExpr>(RefExpr)) { + llvm::APSInt DepCounter(/*BitWidth=*/32); + llvm::APSInt TotalDepCount(/*BitWidth=*/32); + if (DepKind == OMPC_DEPEND_sink) { + if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) { + TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context); + TotalDepCount.setIsUnsigned(/*Val=*/true); + } + } + if ((DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) || + DSAStack->getParentOrderedRegionParam()) { + for (auto &RefExpr : VarList) { + assert(RefExpr && "NULL expr in OpenMP shared clause."); + if (isa<DependentScopeDeclRefExpr>(RefExpr) || + (DepKind == OMPC_DEPEND_sink && CurContext->isDependentContext())) { + // It will be analyzed later. + Vars.push_back(RefExpr); + continue; + } + + SourceLocation ELoc = RefExpr->getExprLoc(); + auto *SimpleExpr = RefExpr->IgnoreParenCasts(); + if (DepKind == OMPC_DEPEND_sink) { + if (DepCounter >= TotalDepCount) { + Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr); + continue; + } + ++DepCounter; + // OpenMP [2.13.9, Summary] + // depend(dependence-type : vec), where dependence-type is: + // 'sink' and where vec is the iteration vector, which has the form: + // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn] + // where n is the value specified by the ordered clause in the loop + // directive, xi denotes the loop iteration variable of the i-th nested + // loop associated with the loop directive, and di is a constant + // non-negative integer. + SimpleExpr = SimpleExpr->IgnoreImplicit(); + auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); + if (!DE) { + OverloadedOperatorKind OOK = OO_None; + SourceLocation OOLoc; + Expr *LHS, *RHS; + if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) { + OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode()); + OOLoc = BO->getOperatorLoc(); + LHS = BO->getLHS()->IgnoreParenImpCasts(); + RHS = BO->getRHS()->IgnoreParenImpCasts(); + } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) { + OOK = OCE->getOperator(); + OOLoc = OCE->getOperatorLoc(); + LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); + RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); + } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) { + OOK = MCE->getMethodDecl() + ->getNameInfo() + .getName() + .getCXXOverloadedOperator(); + OOLoc = MCE->getCallee()->getExprLoc(); + LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts(); + RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); + } else { + Diag(ELoc, diag::err_omp_depend_sink_wrong_expr); + continue; + } + DE = dyn_cast<DeclRefExpr>(LHS); + if (!DE) { + Diag(LHS->getExprLoc(), + diag::err_omp_depend_sink_expected_loop_iteration) + << DSAStack->getParentLoopControlVariable( + DepCounter.getZExtValue()); + continue; + } + if (OOK != OO_Plus && OOK != OO_Minus) { + Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus); + continue; + } + ExprResult Res = VerifyPositiveIntegerConstantInClause( + RHS, OMPC_depend, /*StrictlyPositive=*/false); + if (Res.isInvalid()) + continue; + } + auto *VD = dyn_cast<VarDecl>(DE->getDecl()); + if (!CurContext->isDependentContext() && + DSAStack->getParentOrderedRegionParam() && + (!VD || DepCounter != DSAStack->isParentLoopControlVariable(VD))) { + Diag(DE->getExprLoc(), + diag::err_omp_depend_sink_expected_loop_iteration) + << DSAStack->getParentLoopControlVariable( + DepCounter.getZExtValue()); + continue; + } + } else { + // OpenMP [2.11.1.1, Restrictions, p.3] + // A variable that is part of another variable (such as a field of a + // structure) but is not an array element or an array section cannot + // appear in a depend clause. + auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); + auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); + auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr); + if (!RefExpr->IgnoreParenImpCasts()->isLValue() || + (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) || + (ASE && !ASE->getBase()->getType()->isAnyPointerType() && + !ASE->getBase()->getType()->isArrayType())) { + Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) + << RefExpr->getSourceRange(); + continue; + } + } + + Vars.push_back(RefExpr->IgnoreParenImpCasts()); + } + + if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink && + TotalDepCount > VarList.size() && + DSAStack->getParentOrderedRegionParam()) { + Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) + << DSAStack->getParentLoopControlVariable(VarList.size() + 1); + } + if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink && + Vars.empty()) + return nullptr; + } + + return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind, + DepLoc, ColonLoc, Vars); +} + +OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + Expr *ValExpr = Device; + + // OpenMP [2.9.1, Restrictions] + // The device expression must evaluate to a non-negative integer value. + if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_device, + /*StrictlyPositive=*/false)) + return nullptr; + + return new (Context) OMPDeviceClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +static bool IsCXXRecordForMappable(Sema &SemaRef, SourceLocation Loc, + DSAStackTy *Stack, CXXRecordDecl *RD) { + if (!RD || RD->isInvalidDecl()) + return true; + + if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) + if (auto *CTD = CTSD->getSpecializedTemplate()) + RD = CTD->getTemplatedDecl(); + auto QTy = SemaRef.Context.getRecordType(RD); + if (RD->isDynamicClass()) { + SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; + SemaRef.Diag(RD->getLocation(), diag::note_omp_polymorphic_in_target); + return false; + } + auto *DC = RD; + bool IsCorrect = true; + for (auto *I : DC->decls()) { + if (I) { + if (auto *MD = dyn_cast<CXXMethodDecl>(I)) { + if (MD->isStatic()) { + SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; + SemaRef.Diag(MD->getLocation(), + diag::note_omp_static_member_in_target); + IsCorrect = false; + } + } else if (auto *VD = dyn_cast<VarDecl>(I)) { + if (VD->isStaticDataMember()) { + SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; + SemaRef.Diag(VD->getLocation(), + diag::note_omp_static_member_in_target); + IsCorrect = false; + } + } + } + } + + for (auto &I : RD->bases()) { + if (!IsCXXRecordForMappable(SemaRef, I.getLocStart(), Stack, + I.getType()->getAsCXXRecordDecl())) + IsCorrect = false; + } + return IsCorrect; +} + +static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, + DSAStackTy *Stack, QualType QTy) { + NamedDecl *ND; + if (QTy->isIncompleteType(&ND)) { + SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR; + return false; + } else if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(ND)) { + if (!RD->isInvalidDecl() && + !IsCXXRecordForMappable(SemaRef, SL, Stack, RD)) + return false; + } + return true; +} + +OMPClause *Sema::ActOnOpenMPMapClause( + OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType, + SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { + SmallVector<Expr *, 4> Vars; + + for (auto &RE : VarList) { + assert(RE && "Null expr in omp map"); + if (isa<DependentScopeDeclRefExpr>(RE)) { // It will be analyzed later. - Vars.push_back(RefExpr); + Vars.push_back(RE); continue; } + SourceLocation ELoc = RE->getExprLoc(); - SourceLocation ELoc = RefExpr->getExprLoc(); - // OpenMP [2.11.1.1, Restrictions, p.3] - // A variable that is part of another variable (such as a field of a + // OpenMP [2.14.5, Restrictions] + // A variable that is part of another variable (such as field of a // structure) but is not an array element or an array section cannot appear - // in a depend clause. - auto *SimpleExpr = RefExpr->IgnoreParenCasts(); - DeclRefExpr *DE = dyn_cast<DeclRefExpr>(SimpleExpr); - ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); - if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (!ASE && !DE) || + // in a map clause. + auto *VE = RE->IgnoreParenLValueCasts(); + + if (VE->isValueDependent() || VE->isTypeDependent() || + VE->isInstantiationDependent() || + VE->containsUnexpandedParameterPack()) { + // It will be analyzed later. + Vars.push_back(RE); + continue; + } + + auto *SimpleExpr = RE->IgnoreParenCasts(); + auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); + auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); + auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr); + + if (!RE->IgnoreParenImpCasts()->isLValue() || + (!OASE && !ASE && !DE) || (DE && !isa<VarDecl>(DE->getDecl())) || (ASE && !ASE->getBase()->getType()->isAnyPointerType() && !ASE->getBase()->getType()->isArrayType())) { Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) - << RefExpr->getSourceRange(); + << RE->getSourceRange(); continue; } - Vars.push_back(RefExpr->IgnoreParenImpCasts()); - } + Decl *D = nullptr; + if (DE) { + D = DE->getDecl(); + } else if (ASE) { + auto *B = ASE->getBase()->IgnoreParenCasts(); + D = dyn_cast<DeclRefExpr>(B)->getDecl(); + } else if (OASE) { + auto *B = OASE->getBase(); + D = dyn_cast<DeclRefExpr>(B)->getDecl(); + } + assert(D && "Null decl on map clause."); + auto *VD = cast<VarDecl>(D); + + // OpenMP [2.14.5, Restrictions, p.8] + // threadprivate variables cannot appear in a map clause. + if (DSAStack->isThreadPrivate(VD)) { + auto DVar = DSAStack->getTopDSA(VD, false); + Diag(ELoc, diag::err_omp_threadprivate_in_map); + ReportOriginalDSA(*this, DSAStack, VD, DVar); + continue; + } + + // OpenMP [2.14.5, Restrictions, p.2] + // At most one list item can be an array item derived from a given variable + // in map clauses of the same construct. + // OpenMP [2.14.5, Restrictions, p.3] + // List items of map clauses in the same construct must not share original + // storage. + // OpenMP [2.14.5, Restrictions, C/C++, p.2] + // A variable for which the type is pointer, reference to array, or + // reference to pointer and an array section derived from that variable + // must not appear as list items of map clauses of the same construct. + DSAStackTy::MapInfo MI = DSAStack->IsMappedInCurrentRegion(VD); + if (MI.RefExpr) { + Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc; + Diag(MI.RefExpr->getExprLoc(), diag::note_used_here) + << MI.RefExpr->getSourceRange(); + continue; + } + + // OpenMP [2.14.5, Restrictions, C/C++, p.3,4] + // A variable for which the type is pointer, reference to array, or + // reference to pointer must not appear as a list item if the enclosing + // device data environment already contains an array section derived from + // that variable. + // An array section derived from a variable for which the type is pointer, + // reference to array, or reference to pointer must not appear as a list + // item if the enclosing device data environment already contains that + // variable. + QualType Type = VD->getType(); + MI = DSAStack->getMapInfoForVar(VD); + if (MI.RefExpr && (isa<DeclRefExpr>(MI.RefExpr->IgnoreParenLValueCasts()) != + isa<DeclRefExpr>(VE)) && + (Type->isPointerType() || Type->isReferenceType())) { + Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc; + Diag(MI.RefExpr->getExprLoc(), diag::note_used_here) + << MI.RefExpr->getSourceRange(); + continue; + } + // OpenMP [2.14.5, Restrictions, C/C++, p.7] + // A list item must have a mappable type. + if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), *this, + DSAStack, Type)) + continue; + + Vars.push_back(RE); + MI.RefExpr = RE; + DSAStack->addMapInfoForVar(VD, MI); + } if (Vars.empty()) return nullptr; - return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind, - DepLoc, ColonLoc, Vars); + return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, + MapTypeModifier, MapType, MapLoc); +} + +OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + Expr *ValExpr = NumTeams; + + // OpenMP [teams Constrcut, Restrictions] + // The num_teams expression must evaluate to a positive integer value. + if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams, + /*StrictlyPositive=*/true)) + return nullptr; + + return new (Context) OMPNumTeamsClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + Expr *ValExpr = ThreadLimit; + + // OpenMP [teams Constrcut, Restrictions] + // The thread_limit expression must evaluate to a positive integer value. + if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit, + /*StrictlyPositive=*/true)) + return nullptr; + + return new (Context) OMPThreadLimitClause(ValExpr, StartLoc, LParenLoc, + EndLoc); +} + +OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + Expr *ValExpr = Priority; + + // OpenMP [2.9.1, task Constrcut] + // The priority-value is a non-negative numerical scalar expression. + if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_priority, + /*StrictlyPositive=*/false)) + return nullptr; + + return new (Context) OMPPriorityClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + Expr *ValExpr = Grainsize; + + // OpenMP [2.9.2, taskloop Constrcut] + // The parameter of the grainsize clause must be a positive integer + // expression. + if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize, + /*StrictlyPositive=*/true)) + return nullptr; + + return new (Context) OMPGrainsizeClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + Expr *ValExpr = NumTasks; + + // OpenMP [2.9.2, taskloop Constrcut] + // The parameter of the num_tasks clause must be a positive integer + // expression. + if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks, + /*StrictlyPositive=*/true)) + return nullptr; + + return new (Context) OMPNumTasksClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + // OpenMP [2.13.2, critical construct, Description] + // ... where hint-expression is an integer constant expression that evaluates + // to a valid lock hint. + ExprResult HintExpr = VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint); + if (HintExpr.isInvalid()) + return nullptr; + return new (Context) + OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 31f581d..1caa94c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -38,6 +38,11 @@ using namespace clang; using namespace sema; +static bool functionHasPassObjectSizeParams(const FunctionDecl *FD) { + return std::any_of(FD->param_begin(), FD->param_end(), + std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>)); +} + /// A convenience routine for creating a decayed reference to a function. static ExprResult CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, @@ -60,12 +65,8 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, DRE->setHadMultipleCandidates(true); S.MarkDeclRefReferenced(DRE); - - ExprResult E = DRE; - E = S.DefaultFunctionArrayConversion(E.get()); - if (E.isInvalid()) - return ExprError(); - return E; + return S.ImpCastExprToType(DRE, S.Context.getPointerType(DRE->getType()), + CK_FunctionToPointerDecay); } static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, @@ -88,7 +89,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, static ImplicitConversionSequence::CompareKind -CompareStandardConversionSequences(Sema &S, +CompareStandardConversionSequences(Sema &S, SourceLocation Loc, const StandardConversionSequence& SCS1, const StandardConversionSequence& SCS2); @@ -98,7 +99,7 @@ CompareQualificationConversions(Sema &S, const StandardConversionSequence& SCS2); static ImplicitConversionSequence::CompareKind -CompareDerivedToBaseConversions(Sema &S, +CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, const StandardConversionSequence& SCS1, const StandardConversionSequence& SCS2); @@ -130,7 +131,11 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { ICR_Complex_Real_Conversion, ICR_Conversion, ICR_Conversion, - ICR_Writeback_Conversion + ICR_Writeback_Conversion, + ICR_Exact_Match, // NOTE(gbiv): This may not be completely right -- + // it was omitted by the patch that added + // ICK_Zero_Event_Conversion + ICR_C_Conversion }; return Rank[(int)Kind]; } @@ -162,7 +167,9 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) { "Complex-real conversion", "Block Pointer conversion", "Transparent Union Conversion", - "Writeback conversion" + "Writeback conversion", + "OpenCL Zero Event Conversion", + "C specific type conversion" }; return Name[Kind]; } @@ -896,6 +903,11 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl(); } + // A using-declaration does not conflict with another declaration + // if one of them is hidden. + if ((OldIsUsingDecl || NewIsUsingDecl) && !isVisible(*I)) + continue; + // If either declaration was introduced by a using declaration, // we'll need to use slightly different rules for matching. // Essentially, these rules are the normal rules, except that @@ -1051,6 +1063,14 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return true; } + // Though pass_object_size is placed on parameters and takes an argument, we + // consider it to be a function-level modifier for the sake of function + // identity. Either the function has one or more parameters with + // pass_object_size or it doesn't. + if (functionHasPassObjectSizeParams(New) != + functionHasPassObjectSizeParams(Old)) + return true; + // enable_if attributes are an order-sensitive part of the signature. for (specific_attr_iterator<EnableIfAttr> NewI = New->specific_attr_begin<EnableIfAttr>(), @@ -1067,6 +1087,25 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return true; } + if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads) { + CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New), + OldTarget = IdentifyCUDATarget(Old); + if (NewTarget == CFT_InvalidTarget || NewTarget == CFT_Global) + return false; + + assert((OldTarget != CFT_InvalidTarget) && "Unexpected invalid target."); + + // Don't allow mixing of HD with other kinds. This guarantees that + // we have only one viable function with this signature on any + // side of CUDA compilation . + if ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice)) + return false; + + // Allow overloading of functions with same signature, but + // different CUDA target attributes. + return NewTarget != OldTarget; + } + // The signatures match; this is not an overload. return false; } @@ -1125,7 +1164,8 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, QualType ToCanon = S.Context.getCanonicalType(ToType).getUnqualifiedType(); if (Constructor->isCopyConstructor() && - (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) { + (FromCanon == ToCanon || + S.IsDerivedFrom(From->getLocStart(), FromCanon, ToCanon))) { // Turn this into a "standard" conversion sequence, so that it // gets ranked with standard conversion sequences. ICS.setStandard(); @@ -1215,7 +1255,7 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType, QualType FromType = From->getType(); if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() && (S.Context.hasSameUnqualifiedType(FromType, ToType) || - S.IsDerivedFrom(FromType, ToType))) { + S.IsDerivedFrom(From->getLocStart(), FromType, ToType))) { ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); ICS.Standard.setFromType(FromType); @@ -1387,7 +1427,7 @@ static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType, bool InOverloadResolution, StandardConversionSequence &SCS, bool CStyle); - + /// IsStandardConversion - Determines whether there is a standard /// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the /// expression From to the type ToType. Standard conversion sequences @@ -1410,13 +1450,10 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, SCS.CopyConstructor = nullptr; // There are no standard conversions for class types in C++, so - // abort early. When overloading in C, however, we do permit - if (FromType->isRecordType() || ToType->isRecordType()) { - if (S.getLangOpts().CPlusPlus) - return false; - - // When we're overloading in C, we allow, as standard conversions, - } + // abort early. When overloading in C, however, we do permit them. + if (S.getLangOpts().CPlusPlus && + (FromType->isRecordType() || ToType->isRecordType())) + return false; // The first conversion can be an lvalue-to-rvalue conversion, // array-to-pointer conversion, or function-to-pointer conversion @@ -1521,6 +1558,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Function-to-pointer conversion (C++ 4.3). SCS.First = ICK_Function_To_Pointer; + if (auto *DRE = dyn_cast<DeclRefExpr>(From->IgnoreParenCasts())) + if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) + if (!S.checkAddressOfFunctionIsAvailable(FD)) + return false; + // An lvalue of function type T can be converted to an rvalue of // type "pointer to T." The result is a pointer to the // function. (C++ 4.3p1). @@ -1625,9 +1667,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // tryAtomicConversion has updated the standard conversion sequence // appropriately. return true; - } else if (ToType->isEventT() && + } else if (ToType->isEventT() && From->isIntegerConstantExpr(S.getASTContext()) && - (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) { + From->EvaluateKnownConstInt(S.getASTContext()) == 0) { SCS.Second = ICK_Zero_Event_Conversion; FromType = ToType; } else { @@ -1666,11 +1708,28 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, } SCS.setToType(2, FromType); + if (CanonFrom == CanonTo) + return true; + // If we have not converted the argument type to the parameter type, - // this is a bad conversion sequence. - if (CanonFrom != CanonTo) + // this is a bad conversion sequence, unless we're resolving an overload in C. + if (S.getLangOpts().CPlusPlus || !InOverloadResolution) + return false; + + ExprResult ER = ExprResult{From}; + auto Conv = S.CheckSingleAssignmentConstraints(ToType, ER, + /*Diagnose=*/false, + /*DiagnoseCFAudited=*/false, + /*ConvertRHS=*/false); + if (Conv != Sema::Compatible) return false; + SCS.setAllToTypes(ToType); + // We need to set all three because we want this conversion to rank terribly, + // and we don't know what conversions it may overlap with. + SCS.First = ICK_C_Only_Conversion; + SCS.Second = ICK_C_Only_Conversion; + SCS.Third = ICK_C_Only_Conversion; return true; } @@ -1763,7 +1822,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // We have already pre-calculated the promotion type, so this is trivial. if (ToType->isIntegerType() && - !RequireCompleteType(From->getLocStart(), FromType, 0)) + isCompleteType(From->getLocStart(), FromType)) return Context.hasSameUnqualifiedType( ToType, FromEnumType->getDecl()->getPromotionType()); } @@ -2060,7 +2119,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, } // MSVC allows implicit function to void* type conversion. - if (getLangOpts().MicrosoftExt && FromPointeeType->isFunctionType() && + if (getLangOpts().MSVCCompat && FromPointeeType->isFunctionType() && ToPointeeType->isVoidType()) { ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, @@ -2094,8 +2153,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, if (getLangOpts().CPlusPlus && FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) && - !RequireCompleteType(From->getLocStart(), FromPointeeType, 0) && - IsDerivedFrom(FromPointeeType, ToPointeeType)) { + IsDerivedFrom(From->getLocStart(), FromPointeeType, ToPointeeType)) { ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, ToType, Context); @@ -2467,6 +2525,18 @@ enum { ft_qualifer_mismatch }; +/// Attempts to get the FunctionProtoType from a Type. Handles +/// MemberFunctionPointers properly. +static const FunctionProtoType *tryGetFunctionProtoType(QualType FromType) { + if (auto *FPT = FromType->getAs<FunctionProtoType>()) + return FPT; + + if (auto *MPT = FromType->getAs<MemberPointerType>()) + return MPT->getPointeeType()->getAs<FunctionProtoType>(); + + return nullptr; +} + /// HandleFunctionTypeMismatch - Gives diagnostic information for differeing /// function types. Catches different number of parameter, mismatch in /// parameter types, and different return types. @@ -2513,8 +2583,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, return; } - const FunctionProtoType *FromFunction = FromType->getAs<FunctionProtoType>(), - *ToFunction = ToType->getAs<FunctionProtoType>(); + const FunctionProtoType *FromFunction = tryGetFunctionProtoType(FromType), + *ToFunction = tryGetFunctionProtoType(ToType); // Both types need to be function types. if (!FromFunction || !ToFunction) { @@ -2621,6 +2691,14 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, // The conversion was successful. Kind = CK_DerivedToBase; } + + if (!IsCStyleOrFunctionalCast && FromPointeeType->isFunctionType() && + ToPointeeType->isVoidType()) { + assert(getLangOpts().MSVCCompat && + "this should only be possible with MSVCCompat!"); + Diag(From->getExprLoc(), diag::ext_ms_impcast_fn_obj) + << From->getSourceRange(); + } } } else if (const ObjCObjectPointerType *ToPtrType = ToType->getAs<ObjCObjectPointerType>()) { @@ -2681,8 +2759,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToClass(ToTypePtr->getClass(), 0); if (!Context.hasSameUnqualifiedType(FromClass, ToClass) && - !RequireCompleteType(From->getLocStart(), ToClass, 0) && - IsDerivedFrom(ToClass, FromClass)) { + IsDerivedFrom(From->getLocStart(), ToClass, FromClass)) { ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(), ToClass.getTypePtr()); return true; @@ -2725,7 +2802,8 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); - bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths); + bool DerivationOkay = + IsDerivedFrom(From->getLocStart(), ToClass, FromClass, Paths); assert(DerivationOkay && "Should not have been called if derivation isn't OK."); (void)DerivationOkay; @@ -3004,14 +3082,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // the parentheses of the initializer. if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) || (From->getType()->getAs<RecordType>() && - S.IsDerivedFrom(From->getType(), ToType))) + S.IsDerivedFrom(From->getLocStart(), From->getType(), ToType))) ConstructorsOnly = true; - S.RequireCompleteType(From->getExprLoc(), ToType, 0); - // RequireCompleteType may have returned true due to some invalid decl - // during template instantiation, but ToType may be complete enough now - // to try to recover. - if (ToType->isIncompleteType()) { + if (!S.isCompleteType(From->getExprLoc(), ToType)) { // We're not going to find any constructors. } else if (CXXRecordDecl *ToRecordDecl = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) { @@ -3085,7 +3159,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Enumerate conversion functions, if we're allowed to. if (ConstructorsOnly || isa<InitListExpr>(From)) { - } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), 0)) { + } else if (!S.isCompleteType(From->getLocStart(), From->getType())) { // No conversion functions from incomplete types. } else if (const RecordType *FromRecordType = From->getType()->getAs<RecordType>()) { @@ -3212,7 +3286,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { diag::err_typecheck_nonviable_condition_incomplete, From->getType(), From->getSourceRange())) Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition) - << From->getType() << From->getSourceRange() << ToType; + << false << From->getType() << From->getSourceRange() << ToType; } else return false; CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From); @@ -3264,7 +3338,7 @@ static bool hasDeprecatedStringLiteralToCharPtrConversion( /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2). static ImplicitConversionSequence::CompareKind -CompareImplicitConversionSequences(Sema &S, +CompareImplicitConversionSequences(Sema &S, SourceLocation Loc, const ImplicitConversionSequence& ICS1, const ImplicitConversionSequence& ICS2) { @@ -3344,7 +3418,7 @@ CompareImplicitConversionSequences(Sema &S, if (ICS1.isStandard()) // Standard conversion sequence S1 is a better conversion sequence than // standard conversion sequence S2 if [...] - Result = CompareStandardConversionSequences(S, + Result = CompareStandardConversionSequences(S, Loc, ICS1.Standard, ICS2.Standard); else if (ICS1.isUserDefined()) { // User-defined conversion sequence U1 is a better conversion @@ -3355,7 +3429,7 @@ CompareImplicitConversionSequences(Sema &S, // U2 (C++ 13.3.3.2p3). if (ICS1.UserDefined.ConversionFunction == ICS2.UserDefined.ConversionFunction) - Result = CompareStandardConversionSequences(S, + Result = CompareStandardConversionSequences(S, Loc, ICS1.UserDefined.After, ICS2.UserDefined.After); else @@ -3453,7 +3527,7 @@ isBetterReferenceBindingKind(const StandardConversionSequence &SCS1, /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2p3). static ImplicitConversionSequence::CompareKind -CompareStandardConversionSequences(Sema &S, +CompareStandardConversionSequences(Sema &S, SourceLocation Loc, const StandardConversionSequence& SCS1, const StandardConversionSequence& SCS2) { @@ -3509,7 +3583,7 @@ CompareStandardConversionSequences(Sema &S, // Neither conversion sequence converts to a void pointer; compare // their derived-to-base conversions. if (ImplicitConversionSequence::CompareKind DerivedCK - = CompareDerivedToBaseConversions(S, SCS1, SCS2)) + = CompareDerivedToBaseConversions(S, Loc, SCS1, SCS2)) return DerivedCK; } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid && !S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) { @@ -3529,9 +3603,9 @@ CompareStandardConversionSequences(Sema &S, QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType(); QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType(); - if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1)) return ImplicitConversionSequence::Better; - else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) + else if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2)) return ImplicitConversionSequence::Worse; // Objective-C++: If one interface is more specific than the @@ -3739,7 +3813,7 @@ CompareQualificationConversions(Sema &S, /// [over.ics.rank]p4b3). As part of these checks, we also look at /// conversions between Objective-C interface types. static ImplicitConversionSequence::CompareKind -CompareDerivedToBaseConversions(Sema &S, +CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, const StandardConversionSequence& SCS1, const StandardConversionSequence& SCS2) { QualType FromType1 = SCS1.getFromType(); @@ -3782,17 +3856,17 @@ CompareDerivedToBaseConversions(Sema &S, // -- conversion of C* to B* is better than conversion of C* to A*, if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { - if (S.IsDerivedFrom(ToPointee1, ToPointee2)) + if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2)) return ImplicitConversionSequence::Better; - else if (S.IsDerivedFrom(ToPointee2, ToPointee1)) + else if (S.IsDerivedFrom(Loc, ToPointee2, ToPointee1)) return ImplicitConversionSequence::Worse; } // -- conversion of B* to A* is better than conversion of C* to A*, if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) { - if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1)) return ImplicitConversionSequence::Better; - else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) + else if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2)) return ImplicitConversionSequence::Worse; } } else if (SCS1.Second == ICK_Pointer_Conversion && @@ -3889,16 +3963,16 @@ CompareDerivedToBaseConversions(Sema &S, QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType(); // conversion of A::* to B::* is better than conversion of A::* to C::*, if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { - if (S.IsDerivedFrom(ToPointee1, ToPointee2)) + if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2)) return ImplicitConversionSequence::Worse; - else if (S.IsDerivedFrom(ToPointee2, ToPointee1)) + else if (S.IsDerivedFrom(Loc, ToPointee2, ToPointee1)) return ImplicitConversionSequence::Better; } // conversion of B::* to C::* is better than conversion of A::* to C::* if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) { - if (S.IsDerivedFrom(FromPointee1, FromPointee2)) + if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2)) return ImplicitConversionSequence::Better; - else if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + else if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1)) return ImplicitConversionSequence::Worse; } } @@ -3910,9 +3984,9 @@ CompareDerivedToBaseConversions(Sema &S, // reference of type A&, if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) && !S.Context.hasSameUnqualifiedType(ToType1, ToType2)) { - if (S.IsDerivedFrom(ToType1, ToType2)) + if (S.IsDerivedFrom(Loc, ToType1, ToType2)) return ImplicitConversionSequence::Better; - else if (S.IsDerivedFrom(ToType2, ToType1)) + else if (S.IsDerivedFrom(Loc, ToType2, ToType1)) return ImplicitConversionSequence::Worse; } @@ -3922,9 +3996,9 @@ CompareDerivedToBaseConversions(Sema &S, // reference of type A&, if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) && S.Context.hasSameUnqualifiedType(ToType1, ToType2)) { - if (S.IsDerivedFrom(FromType2, FromType1)) + if (S.IsDerivedFrom(Loc, FromType2, FromType1)) return ImplicitConversionSequence::Better; - else if (S.IsDerivedFrom(FromType1, FromType2)) + else if (S.IsDerivedFrom(Loc, FromType1, FromType2)) return ImplicitConversionSequence::Worse; } } @@ -3973,9 +4047,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, ObjCLifetimeConversion = false; if (UnqualT1 == UnqualT2) { // Nothing to do. - } else if (!RequireCompleteType(Loc, OrigT2, 0) && + } else if (isCompleteType(Loc, OrigT2) && isTypeValid(UnqualT1) && isTypeValid(UnqualT2) && - IsDerivedFrom(UnqualT2, UnqualT1)) + IsDerivedFrom(Loc, UnqualT2, UnqualT1)) DerivedToBase = true; else if (UnqualT1->isObjCObjectOrInterfaceType() && UnqualT2->isObjCObjectOrInterfaceType() && @@ -4240,7 +4314,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // conversion functions (13.3.1.6) and choosing the best // one through overload resolution (13.3)), if (!SuppressUserConversions && T2->isRecordType() && - !S.RequireCompleteType(DeclLoc, T2, 0) && + S.isCompleteType(DeclLoc, T2) && RefRelationship == Sema::Ref_Incompatible) { if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc, Init, T2, /*AllowRvalues=*/false, @@ -4303,7 +4377,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // in the second case (or, in either case, to an appropriate base // class subobject). if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible && - T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) && + T2->isRecordType() && S.isCompleteType(DeclLoc, T2) && FindConversionForRefInit(S, ICS, DeclType, DeclLoc, Init, T2, /*AllowRvalues=*/true, AllowExplicit)) { @@ -4441,7 +4515,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // We need a complete type for what follows. Incomplete types can never be // initialized from init lists. - if (S.RequireCompleteType(From->getLocStart(), ToType, 0)) + if (!S.isCompleteType(From->getLocStart(), ToType)) return Result; // Per DR1467: @@ -4458,7 +4532,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, if (ToType->isRecordType()) { QualType InitType = From->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, ToType) || - S.IsDerivedFrom(InitType, ToType)) + S.IsDerivedFrom(From->getLocStart(), InitType, ToType)) return TryCopyInitialization(S, From->getInit(0), ToType, SuppressUserConversions, InOverloadResolution, @@ -4515,7 +4589,8 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, } // Otherwise, look for the worst conversion. if (Result.isBad() || - CompareImplicitConversionSequences(S, ICS, Result) == + CompareImplicitConversionSequences(S, From->getLocStart(), ICS, + Result) == ImplicitConversionSequence::Worse) Result = ICS; } @@ -4722,7 +4797,7 @@ static bool TryCopyInitialization(const CanQualType FromQTy, /// parameter of the given member function (@c Method) from the /// expression @p From. static ImplicitConversionSequence -TryObjectArgumentInitialization(Sema &S, QualType FromType, +TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, Expr::Classification FromClassification, CXXMethodDecl *Method, CXXRecordDecl *ActingContext) { @@ -4782,7 +4857,7 @@ TryObjectArgumentInitialization(Sema &S, QualType FromType, ImplicitConversionKind SecondKind; if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { SecondKind = ICK_Identity; - } else if (S.IsDerivedFrom(FromType, ClassType)) + } else if (S.IsDerivedFrom(Loc, FromType, ClassType)) SecondKind = ICK_Derived_To_Base; else { ICS.setBad(BadConversionSequence::unrelated_class, @@ -4857,7 +4932,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From, // Note that we always use the true parent context when performing // the actual argument initialization. ImplicitConversionSequence ICS = TryObjectArgumentInitialization( - *this, From->getType(), FromClassification, Method, Method->getParent()); + *this, From->getLocStart(), From->getType(), FromClassification, Method, + Method->getParent()); if (ICS.isBad()) { if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) { Qualifiers FromQs = FromRecordType.getQualifiers(); @@ -4969,6 +5045,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_TransparentUnionConversion: case ICK_Writeback_Conversion: case ICK_Zero_Event_Conversion: + case ICK_C_Only_Conversion: return false; case ICK_Lvalue_To_Rvalue: @@ -5372,14 +5449,15 @@ ExprResult Sema::PerformContextualImplicitConversion( Expr *From; TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From) - : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {} + : Converter(Converter), From(From) {} void diagnose(Sema &S, SourceLocation Loc, QualType T) override { Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange(); } } IncompleteDiagnoser(Converter, From); - if (RequireCompleteType(Loc, T, IncompleteDiagnoser)) + if (Converter.Suppress ? !isCompleteType(Loc, T) + : RequireCompleteType(Loc, T, IncompleteDiagnoser)) return From; // Look for a conversion to an integral or enumeration type. @@ -5637,10 +5715,10 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // A member function template is never instantiated to perform the copy // of a class object to an object of its class type. QualType ClassType = Context.getTypeDeclType(Constructor->getParent()); - if (Args.size() == 1 && - Constructor->isSpecializationCopyingObject() && + if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() && (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) || - IsDerivedFrom(Args[0]->getType(), ClassType))) { + IsDerivedFrom(Args[0]->getLocStart(), Args[0]->getType(), + ClassType))) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_illegal_constructor; return; @@ -5761,7 +5839,7 @@ ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, Match = false; break; } - + ImplicitConversionSequence ConversionState = TryCopyInitialization(*this, argExpr, param->getType(), /*SuppressUserConversions*/false, @@ -5809,27 +5887,36 @@ ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, return nullptr; } -static bool IsNotEnableIfAttr(Attr *A) { return !isa<EnableIfAttr>(A); } +// specific_attr_iterator iterates over enable_if attributes in reverse, and +// enable_if is order-sensitive. As a result, we need to reverse things +// sometimes. Size of 4 elements is arbitrary. +static SmallVector<EnableIfAttr *, 4> +getOrderedEnableIfAttrs(const FunctionDecl *Function) { + SmallVector<EnableIfAttr *, 4> Result; + if (!Function->hasAttrs()) + return Result; + + const auto &FuncAttrs = Function->getAttrs(); + for (Attr *Attr : FuncAttrs) + if (auto *EnableIf = dyn_cast<EnableIfAttr>(Attr)) + Result.push_back(EnableIf); + + std::reverse(Result.begin(), Result.end()); + return Result; +} EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, bool MissingImplicitThis) { - // FIXME: specific_attr_iterator<EnableIfAttr> iterates in reverse order, but - // we need to find the first failing one. - if (!Function->hasAttrs()) - return nullptr; - AttrVec Attrs = Function->getAttrs(); - AttrVec::iterator E = std::remove_if(Attrs.begin(), Attrs.end(), - IsNotEnableIfAttr); - if (Attrs.begin() == E) + auto EnableIfAttrs = getOrderedEnableIfAttrs(Function); + if (EnableIfAttrs.empty()) return nullptr; - std::reverse(Attrs.begin(), E); SFINAETrap Trap(*this); - - // Convert the arguments. SmallVector<Expr *, 16> ConvertedArgs; bool InitializationFailed = false; bool ContainsValueDependentExpr = false; + + // Convert the arguments. for (unsigned i = 0, e = Args.size(); i != e; ++i) { if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) && !cast<CXXMethodDecl>(Function)->isStatic() && @@ -5861,11 +5948,32 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, } if (InitializationFailed || Trap.hasErrorOccurred()) - return cast<EnableIfAttr>(Attrs[0]); + return EnableIfAttrs[0]; + + // Push default arguments if needed. + if (!Function->isVariadic() && Args.size() < Function->getNumParams()) { + for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) { + ParmVarDecl *P = Function->getParamDecl(i); + ExprResult R = PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + Function->getParamDecl(i)), + SourceLocation(), + P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg() + : P->getDefaultArg()); + if (R.isInvalid()) { + InitializationFailed = true; + break; + } + ContainsValueDependentExpr |= R.get()->isValueDependent(); + ConvertedArgs.push_back(R.get()); + } + + if (InitializationFailed || Trap.hasErrorOccurred()) + return EnableIfAttrs[0]; + } - for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) { + for (auto *EIA : EnableIfAttrs) { APValue Result; - EnableIfAttr *EIA = cast<EnableIfAttr>(*I); if (EIA->getCond()->isValueDependent()) { // Don't even try now, we'll examine it after instantiation. continue; @@ -6027,9 +6135,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, else { // Determine the implicit conversion sequence for the object // parameter. - Candidate.Conversions[0] - = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification, - Method, ActingContext); + Candidate.Conversions[0] = TryObjectArgumentInitialization( + *this, CandidateSet.getLocation(), ObjectType, ObjectClassification, + Method, ActingContext); if (Candidate.Conversions[0].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -6286,10 +6394,9 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, CXXRecordDecl *ConversionContext = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl()); - Candidate.Conversions[0] - = TryObjectArgumentInitialization(*this, From->getType(), - From->Classify(Context), - Conversion, ConversionContext); + Candidate.Conversions[0] = TryObjectArgumentInitialization( + *this, CandidateSet.getLocation(), From->getType(), + From->Classify(Context), Conversion, ConversionContext); if (Candidate.Conversions[0].isBad()) { Candidate.Viable = false; @@ -6303,7 +6410,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, QualType FromCanon = Context.getCanonicalType(From->getType().getUnqualifiedType()); QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType(); - if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) { + if (FromCanon == ToCanon || + IsDerivedFrom(CandidateSet.getLocation(), FromCanon, ToCanon)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_trivial_conversion; return; @@ -6325,7 +6433,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, &ConversionRef, VK_RValue); QualType ConversionType = Conversion->getConversionType(); - if (RequireCompleteType(From->getLocStart(), ConversionType, 0)) { + if (!isCompleteType(From->getLocStart(), ConversionType)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_final_conversion; return; @@ -6463,10 +6571,9 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, // Determine the implicit conversion sequence for the implicit // object parameter. - ImplicitConversionSequence ObjectInit - = TryObjectArgumentInitialization(*this, Object->getType(), - Object->Classify(Context), - Conversion, ActingContext); + ImplicitConversionSequence ObjectInit = TryObjectArgumentInitialization( + *this, CandidateSet.getLocation(), Object->getType(), + Object->Classify(Context), Conversion, ActingContext); if (ObjectInit.isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -6575,7 +6682,8 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, // the set of member candidates is empty. if (const RecordType *T1Rec = T1->getAs<RecordType>()) { // Complete the type if it can be completed. - RequireCompleteType(OpLoc, T1, 0); + if (!isCompleteType(OpLoc, T1) && !T1Rec->isBeingDefined()) + return; // If the type is neither complete nor being defined, bail out now. if (!T1Rec->getDecl()->getDefinition()) return; @@ -6924,7 +7032,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, HasNullPtrType = true; } else if (AllowUserConversions && TyRec) { // No conversion functions in incomplete types. - if (SemaRef.RequireCompleteType(Loc, Ty, 0)) + if (!SemaRef.isCompleteType(Loc, Ty)) return; CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); @@ -7527,7 +7635,7 @@ public: llvm::SmallPtrSet<QualType, 8> AddedTypes; for (int Arg = 0; Arg < 2; ++Arg) { - QualType AsymetricParamTypes[2] = { + QualType AsymmetricParamTypes[2] = { S.Context.getPointerDiffType(), S.Context.getPointerDiffType(), }; @@ -7539,11 +7647,11 @@ public: if (!PointeeTy->isObjectType()) continue; - AsymetricParamTypes[Arg] = *Ptr; + AsymmetricParamTypes[Arg] = *Ptr; if (Arg == 0 || Op == OO_Plus) { // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t) // T* operator+(ptrdiff_t, T*); - S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, CandidateSet); + S.AddBuiltinCandidate(*Ptr, AsymmetricParamTypes, Args, CandidateSet); } if (Op == OO_Minus) { // ptrdiff_t operator-(T, T); @@ -8013,7 +8121,7 @@ public: const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr); QualType C2 = QualType(mptr->getClass(), 0); C2 = C2.getUnqualifiedType(); - if (C1 != C2 && !S.IsDerivedFrom(C1, C2)) + if (C1 != C2 && !S.IsDerivedFrom(CandidateSet.getLocation(), C1, C2)) break; QualType ParamTypes[2] = { *Ptr, *MemPtr }; // build CV12 T& @@ -8157,9 +8265,11 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, case OO_Comma: case OO_Arrow: + case OO_Coawait: // C++ [over.match.oper]p3: - // -- For the operator ',', the unary operator '&', or the - // operator '->', the built-in candidates set is empty. + // -- For the operator ',', the unary operator '&', the + // operator '->', or the operator 'co_await', the + // built-in candidates set is empty. break; case OO_Plus: // '+' is either unary or binary @@ -8328,6 +8438,44 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, } } +// Determines whether Cand1 is "better" in terms of its enable_if attrs than +// Cand2 for overloading. This function assumes that all of the enable_if attrs +// on Cand1 and Cand2 have conditions that evaluate to true. +// +// Cand1's set of enable_if attributes are said to be "better" than Cand2's iff +// Cand1's first N enable_if attributes have precisely the same conditions as +// Cand2's first N enable_if attributes (where N = the number of enable_if +// attributes on Cand2), and Cand1 has more than N enable_if attributes. +static bool hasBetterEnableIfAttrs(Sema &S, const FunctionDecl *Cand1, + const FunctionDecl *Cand2) { + + // FIXME: The next several lines are just + // specific_attr_iterator<EnableIfAttr> but going in declaration order, + // instead of reverse order which is how they're stored in the AST. + auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1); + auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2); + + // Candidate 1 is better if it has strictly more attributes and + // the common sequence is identical. + if (Cand1Attrs.size() <= Cand2Attrs.size()) + return false; + + auto Cand1I = Cand1Attrs.begin(); + llvm::FoldingSetNodeID Cand1ID, Cand2ID; + for (auto &Cand2A : Cand2Attrs) { + Cand1ID.clear(); + Cand2ID.clear(); + + auto &Cand1A = *Cand1I++; + Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true); + Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true); + if (Cand1ID != Cand2ID) + return false; + } + + return true; +} + /// isBetterOverloadCandidate - Determines whether the first overload /// candidate is a better candidate than the second (C++ 13.3.3p1). bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1, @@ -8359,7 +8507,7 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1, assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch"); bool HasBetterConversion = false; for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { - switch (CompareImplicitConversionSequences(S, + switch (CompareImplicitConversionSequences(S, Loc, Cand1.Conversions[ArgIdx], Cand2.Conversions[ArgIdx])) { case ImplicitConversionSequence::Better: @@ -8398,7 +8546,7 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1, ImplicitConversionSequence::CompareKind Result = compareConversionFunctions(S, Cand1.Function, Cand2.Function); if (Result == ImplicitConversionSequence::Indistinguishable) - Result = CompareStandardConversionSequences(S, + Result = CompareStandardConversionSequences(S, Loc, Cand1.FinalConversion, Cand2.FinalConversion); @@ -8438,51 +8586,90 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1, // Check for enable_if value-based overload resolution. if (Cand1.Function && Cand2.Function && (Cand1.Function->hasAttr<EnableIfAttr>() || - Cand2.Function->hasAttr<EnableIfAttr>())) { - // FIXME: The next several lines are just - // specific_attr_iterator<EnableIfAttr> but going in declaration order, - // instead of reverse order which is how they're stored in the AST. - AttrVec Cand1Attrs; - if (Cand1.Function->hasAttrs()) { - Cand1Attrs = Cand1.Function->getAttrs(); - Cand1Attrs.erase(std::remove_if(Cand1Attrs.begin(), Cand1Attrs.end(), - IsNotEnableIfAttr), - Cand1Attrs.end()); - std::reverse(Cand1Attrs.begin(), Cand1Attrs.end()); - } - - AttrVec Cand2Attrs; - if (Cand2.Function->hasAttrs()) { - Cand2Attrs = Cand2.Function->getAttrs(); - Cand2Attrs.erase(std::remove_if(Cand2Attrs.begin(), Cand2Attrs.end(), - IsNotEnableIfAttr), - Cand2Attrs.end()); - std::reverse(Cand2Attrs.begin(), Cand2Attrs.end()); - } - - // Candidate 1 is better if it has strictly more attributes and - // the common sequence is identical. - if (Cand1Attrs.size() <= Cand2Attrs.size()) - return false; + Cand2.Function->hasAttr<EnableIfAttr>())) + return hasBetterEnableIfAttrs(S, Cand1.Function, Cand2.Function); + + if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads && + Cand1.Function && Cand2.Function) { + FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext); + return S.IdentifyCUDAPreference(Caller, Cand1.Function) > + S.IdentifyCUDAPreference(Caller, Cand2.Function); + } + + bool HasPS1 = Cand1.Function != nullptr && + functionHasPassObjectSizeParams(Cand1.Function); + bool HasPS2 = Cand2.Function != nullptr && + functionHasPassObjectSizeParams(Cand2.Function); + return HasPS1 != HasPS2 && HasPS1; +} + +/// Determine whether two declarations are "equivalent" for the purposes of +/// name lookup and overload resolution. This applies when the same internal/no +/// linkage entity is defined by two modules (probably by textually including +/// the same header). In such a case, we don't consider the declarations to +/// declare the same entity, but we also don't want lookups with both +/// declarations visible to be ambiguous in some cases (this happens when using +/// a modularized libstdc++). +bool Sema::isEquivalentInternalLinkageDeclaration(const NamedDecl *A, + const NamedDecl *B) { + auto *VA = dyn_cast_or_null<ValueDecl>(A); + auto *VB = dyn_cast_or_null<ValueDecl>(B); + if (!VA || !VB) + return false; - auto Cand1I = Cand1Attrs.begin(); - for (auto &Cand2A : Cand2Attrs) { - auto &Cand1A = *Cand1I++; - llvm::FoldingSetNodeID Cand1ID, Cand2ID; - cast<EnableIfAttr>(Cand1A)->getCond()->Profile(Cand1ID, - S.getASTContext(), true); - cast<EnableIfAttr>(Cand2A)->getCond()->Profile(Cand2ID, - S.getASTContext(), true); - if (Cand1ID != Cand2ID) - return false; - } + // The declarations must be declaring the same name as an internal linkage + // entity in different modules. + if (!VA->getDeclContext()->getRedeclContext()->Equals( + VB->getDeclContext()->getRedeclContext()) || + getOwningModule(const_cast<ValueDecl *>(VA)) == + getOwningModule(const_cast<ValueDecl *>(VB)) || + VA->isExternallyVisible() || VB->isExternallyVisible()) + return false; + // Check that the declarations appear to be equivalent. + // + // FIXME: Checking the type isn't really enough to resolve the ambiguity. + // For constants and functions, we should check the initializer or body is + // the same. For non-constant variables, we shouldn't allow it at all. + if (Context.hasSameType(VA->getType(), VB->getType())) return true; + + // Enum constants within unnamed enumerations will have different types, but + // may still be similar enough to be interchangeable for our purposes. + if (auto *EA = dyn_cast<EnumConstantDecl>(VA)) { + if (auto *EB = dyn_cast<EnumConstantDecl>(VB)) { + // Only handle anonymous enums. If the enumerations were named and + // equivalent, they would have been merged to the same type. + auto *EnumA = cast<EnumDecl>(EA->getDeclContext()); + auto *EnumB = cast<EnumDecl>(EB->getDeclContext()); + if (EnumA->hasNameForLinkage() || EnumB->hasNameForLinkage() || + !Context.hasSameType(EnumA->getIntegerType(), + EnumB->getIntegerType())) + return false; + // Allow this only if the value is the same for both enumerators. + return llvm::APSInt::isSameValue(EA->getInitVal(), EB->getInitVal()); + } } + // Nothing else is sufficiently similar. return false; } +void Sema::diagnoseEquivalentInternalLinkageDeclarations( + SourceLocation Loc, const NamedDecl *D, ArrayRef<const NamedDecl *> Equiv) { + Diag(Loc, diag::ext_equivalent_internal_linkage_decl_in_modules) << D; + + Module *M = getOwningModule(const_cast<NamedDecl*>(D)); + Diag(D->getLocation(), diag::note_equivalent_internal_linkage_decl) + << !M << (M ? M->getFullModuleName() : ""); + + for (auto *E : Equiv) { + Module *M = getOwningModule(const_cast<NamedDecl*>(E)); + Diag(E->getLocation(), diag::note_equivalent_internal_linkage_decl) + << !M << (M ? M->getFullModuleName() : ""); + } +} + /// \brief Computes the best viable function (C++ 13.3.3) /// within an overload candidate set. /// @@ -8510,6 +8697,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, if (Best == end()) return OR_No_Viable_Function; + llvm::SmallVector<const NamedDecl *, 4> EquivalentCands; + // Make sure that this function is better than every other viable // function. If not, we have an ambiguity. for (iterator Cand = begin(); Cand != end(); ++Cand) { @@ -8517,6 +8706,12 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, Cand != Best && !isBetterOverloadCandidate(S, *Best, *Cand, Loc, UserDefinedConversion)) { + if (S.isEquivalentInternalLinkageDeclaration(Best->Function, + Cand->Function)) { + EquivalentCands.push_back(Cand->Function); + continue; + } + Best = end(); return OR_Ambiguous; } @@ -8528,6 +8723,10 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, S.isFunctionConsideredUnavailable(Best->Function))) return OR_Deleted; + if (!EquivalentCands.empty()) + S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function, + EquivalentCands); + return OR_Success; } @@ -8608,12 +8807,85 @@ void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) { } // end anonymous namespace +static bool isFunctionAlwaysEnabled(const ASTContext &Ctx, + const FunctionDecl *FD) { + for (auto *EnableIf : FD->specific_attrs<EnableIfAttr>()) { + bool AlwaysTrue; + if (!EnableIf->getCond()->EvaluateAsBooleanCondition(AlwaysTrue, Ctx)) + return false; + if (!AlwaysTrue) + return false; + } + return true; +} + +/// \brief Returns true if we can take the address of the function. +/// +/// \param Complain - If true, we'll emit a diagnostic +/// \param InOverloadResolution - For the purposes of emitting a diagnostic, are +/// we in overload resolution? +/// \param Loc - The location of the statement we're complaining about. Ignored +/// if we're not complaining, or if we're in overload resolution. +static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD, + bool Complain, + bool InOverloadResolution, + SourceLocation Loc) { + if (!isFunctionAlwaysEnabled(S.Context, FD)) { + if (Complain) { + if (InOverloadResolution) + S.Diag(FD->getLocStart(), + diag::note_addrof_ovl_candidate_disabled_by_enable_if_attr); + else + S.Diag(Loc, diag::err_addrof_function_disabled_by_enable_if_attr) << FD; + } + return false; + } + + auto I = std::find_if(FD->param_begin(), FD->param_end(), + std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>)); + if (I == FD->param_end()) + return true; + + if (Complain) { + // Add one to ParamNo because it's user-facing + unsigned ParamNo = std::distance(FD->param_begin(), I) + 1; + if (InOverloadResolution) + S.Diag(FD->getLocation(), + diag::note_ovl_candidate_has_pass_object_size_params) + << ParamNo; + else + S.Diag(Loc, diag::err_address_of_function_with_pass_object_size_params) + << FD << ParamNo; + } + return false; +} + +static bool checkAddressOfCandidateIsAvailable(Sema &S, + const FunctionDecl *FD) { + return checkAddressOfFunctionIsAvailable(S, FD, /*Complain=*/true, + /*InOverloadResolution=*/true, + /*Loc=*/SourceLocation()); +} + +bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function, + bool Complain, + SourceLocation Loc) { + return ::checkAddressOfFunctionIsAvailable(*this, Function, Complain, + /*InOverloadResolution=*/false, + Loc); +} + // Notes the location of an overload candidate. -void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) { +void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType, + bool TakingAddress) { + if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn)) + return; + std::string FnDesc; OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc); PartialDiagnostic PD = PDiag(diag::note_ovl_candidate) << (unsigned) K << FnDesc; + HandleFunctionTypeMismatch(PD, Fn->getType(), DestType); Diag(Fn->getLocation(), PD); MaybeEmitInheritedConstructorNote(*this, Fn); @@ -8621,7 +8893,8 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) { // Notes the location of all overload candidates designated through // OverloadedExpr -void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) { +void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType, + bool TakingAddress) { assert(OverloadedExpr->getType() == Context.OverloadTy); OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr); @@ -8632,10 +8905,11 @@ void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) { I != IEnd; ++I) { if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType); + NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType, + TakingAddress); } else if (FunctionDecl *Fun = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(Fun, DestType); + NoteOverloadCandidate(Fun, DestType, TakingAddress); } } } @@ -8666,7 +8940,7 @@ void ImplicitConversionSequence::DiagnoseAmbiguousConversion( } static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, - unsigned I) { + unsigned I, bool TakingCandidateAddress) { const ImplicitConversionSequence &Conv = Cand->Conversions[I]; assert(Conv.isBad()); assert(Cand->Function && "for now, candidate must be a function"); @@ -8808,7 +9082,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, FromPtrTy->getPointeeType()) && !FromPtrTy->getPointeeType()->isIncompleteType() && !ToPtrTy->getPointeeType()->isIncompleteType() && - S.IsDerivedFrom(ToPtrTy->getPointeeType(), + S.IsDerivedFrom(SourceLocation(), ToPtrTy->getPointeeType(), FromPtrTy->getPointeeType())) BaseToDerivedConversion = 1; } @@ -8826,7 +9100,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) && !FromTy->isIncompleteType() && !ToRefTy->getPointeeType()->isIncompleteType() && - S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) { + S.IsDerivedFrom(SourceLocation(), ToRefTy->getPointeeType(), FromTy)) { BaseToDerivedConversion = 3; } else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() && ToTy.getNonReferenceType().getCanonicalType() == @@ -8864,7 +9138,11 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, return; } } - + + if (TakingCandidateAddress && + !checkAddressOfCandidateIsAvailable(S, Cand->Function)) + return; + // Emit the generic diagnostic and, optionally, add the hints to it. PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv); FDiag << (unsigned) FnKind << FnDesc @@ -8975,7 +9253,8 @@ static TemplateDecl *getDescribedTemplate(Decl *Templated) { /// Diagnose a failed template-argument deduction. static void DiagnoseBadDeduction(Sema &S, Decl *Templated, DeductionFailureInfo &DeductionFailure, - unsigned NumArgs) { + unsigned NumArgs, + bool TakingCandidateAddress) { TemplateParameter Param = DeductionFailure.getTemplateParameter(); NamedDecl *ParamD; (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) || @@ -9143,6 +9422,11 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated, } } } + + if (TakingCandidateAddress && isa<FunctionDecl>(Templated) && + !checkAddressOfCandidateIsAvailable(S, cast<FunctionDecl>(Templated))) + return; + // FIXME: For generic lambda parameters, check if the function is a lambda // call operator, and if so, emit a prettier and more informative // diagnostic that mentions 'auto' and lambda in addition to @@ -9163,14 +9447,15 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated, /// Diagnose a failed template-argument deduction, for function calls. static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, - unsigned NumArgs) { + unsigned NumArgs, + bool TakingCandidateAddress) { unsigned TDK = Cand->DeductionFailure.Result; if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) { if (CheckArityMismatch(S, Cand, NumArgs)) return; } DiagnoseBadDeduction(S, Cand->Function, // pattern - Cand->DeductionFailure, NumArgs); + Cand->DeductionFailure, NumArgs, TakingCandidateAddress); } /// CUDA: diagnose an invalid call across targets. @@ -9251,7 +9536,8 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) { /// more richly for those diagnostic clients that cared, but we'd /// still have to be just as careful with the default diagnostics. static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, - unsigned NumArgs) { + unsigned NumArgs, + bool TakingCandidateAddress) { FunctionDecl *Fn = Cand->Function; // Note deleted candidates, but only if they're viable. @@ -9279,7 +9565,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, return DiagnoseArityMismatch(S, Cand, NumArgs); case ovl_fail_bad_deduction: - return DiagnoseBadDeduction(S, Cand, NumArgs); + return DiagnoseBadDeduction(S, Cand, NumArgs, TakingCandidateAddress); case ovl_fail_illegal_constructor: { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_illegal_constructor) @@ -9297,7 +9583,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); for (unsigned N = Cand->NumConversions; I != N; ++I) if (Cand->Conversions[I].isBad()) - return DiagnoseBadConversion(S, Cand, I); + return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress); // FIXME: this currently happens when we're called from SemaInit // when user-conversion overload fails. Figure out how to handle @@ -9421,9 +9707,10 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { namespace { struct CompareOverloadCandidatesForDisplay { Sema &S; + SourceLocation Loc; size_t NumArgs; - CompareOverloadCandidatesForDisplay(Sema &S, size_t nArgs) + CompareOverloadCandidatesForDisplay(Sema &S, SourceLocation Loc, size_t nArgs) : S(S), NumArgs(nArgs) {} bool operator()(const OverloadCandidate *L, @@ -9494,7 +9781,7 @@ struct CompareOverloadCandidatesForDisplay { int leftBetter = 0; unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument); for (unsigned E = L->NumConversions; I != E; ++I) { - switch (CompareImplicitConversionSequences(S, + switch (CompareImplicitConversionSequences(S, Loc, L->Conversions[I], R->Conversions[I])) { case ImplicitConversionSequence::Better: @@ -9649,7 +9936,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, } std::sort(Cands.begin(), Cands.end(), - CompareOverloadCandidatesForDisplay(S, Args.size())); + CompareOverloadCandidatesForDisplay(S, OpLoc, Args.size())); bool ReportedAmbiguousConversions = false; @@ -9668,7 +9955,8 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, ++CandsShown; if (Cand->Function) - NoteFunctionCandidate(S, Cand, Args.size()); + NoteFunctionCandidate(S, Cand, Args.size(), + /*TakingCandidateAddress=*/false); else if (Cand->IsSurrogate) NoteSurrogateCandidate(S, Cand); else { @@ -9736,9 +10024,10 @@ struct CompareTemplateSpecCandidatesForDisplay { /// Diagnose a template argument deduction failure. /// We are treating these failures as overload failures due to bad /// deductions. -void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) { +void TemplateSpecCandidate::NoteDeductionFailure(Sema &S, + bool ForTakingAddress) { DiagnoseBadDeduction(S, Specialization, // pattern - DeductionFailure, /*NumArgs=*/0); + DeductionFailure, /*NumArgs=*/0, ForTakingAddress); } void TemplateSpecCandidateSet::destroyCandidates() { @@ -9791,7 +10080,7 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) { assert(Cand->Specialization && "Non-matching built-in candidates are not added to Cands."); - Cand->NoteDeductionFailure(S); + Cand->NoteDeductionFailure(S, ForTakingAddress); } if (I != E) @@ -9836,6 +10125,7 @@ class AddressOfFunctionResolver { bool TargetTypeIsNonStaticMemberFunction; bool FoundNonTemplateFunction; bool StaticMemberFunctionFromBoundPointer; + bool HasComplained; OverloadExpr::FindResult OvlExprInfo; OverloadExpr *OvlExpr; @@ -9852,9 +10142,10 @@ public: !!TargetType->getAs<MemberPointerType>()), FoundNonTemplateFunction(false), StaticMemberFunctionFromBoundPointer(false), + HasComplained(false), OvlExprInfo(OverloadExpr::find(SourceExpr)), OvlExpr(OvlExprInfo.Expression), - FailedCandidates(OvlExpr->getNameLoc()) { + FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) { ExtractUnqualifiedFunctionTypeFromTargetType(); if (TargetFunctionType->isFunctionType()) { @@ -9885,21 +10176,57 @@ public: } if (OvlExpr->hasExplicitTemplateArgs()) - OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs); + OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs); if (FindAllFunctionsThatMatchTargetTypeExactly()) { // C++ [over.over]p4: // If more than one function is selected, [...] - if (Matches.size() > 1) { + if (Matches.size() > 1 && !eliminiateSuboptimalOverloadCandidates()) { if (FoundNonTemplateFunction) EliminateAllTemplateMatches(); else EliminateAllExceptMostSpecializedTemplate(); } } + + if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads && + Matches.size() > 1) + EliminateSuboptimalCudaMatches(); } - + + bool hasComplained() const { return HasComplained; } + private: + // Is A considered a better overload candidate for the desired type than B? + bool isBetterCandidate(const FunctionDecl *A, const FunctionDecl *B) { + return hasBetterEnableIfAttrs(S, A, B); + } + + // Returns true if we've eliminated any (read: all but one) candidates, false + // otherwise. + bool eliminiateSuboptimalOverloadCandidates() { + // Same algorithm as overload resolution -- one pass to pick the "best", + // another pass to be sure that nothing is better than the best. + auto Best = Matches.begin(); + for (auto I = Matches.begin()+1, E = Matches.end(); I != E; ++I) + if (isBetterCandidate(I->second, Best->second)) + Best = I; + + const FunctionDecl *BestFn = Best->second; + auto IsBestOrInferiorToBest = [this, BestFn]( + const std::pair<DeclAccessPair, FunctionDecl *> &Pair) { + return BestFn == Pair.second || isBetterCandidate(BestFn, Pair.second); + }; + + // Note: We explicitly leave Matches unmodified if there isn't a clear best + // option, so we can potentially give the user a better error + if (!std::all_of(Matches.begin(), Matches.end(), IsBestOrInferiorToBest)) + return false; + Matches[0] = *Best; + Matches.resize(1); + return true; + } + bool isTargetTypeAFunction() const { return TargetFunctionType->isFunctionType(); } @@ -9953,6 +10280,10 @@ private: assert(S.isSameOrCompatibleFunctionType( Context.getCanonicalType(Specialization->getType()), Context.getCanonicalType(TargetFunctionType))); + + if (!S.checkAddressOfFunctionIsAvailable(Specialization)) + return false; + Matches.push_back(std::make_pair(CurAccessFunPair, Specialization)); return true; } @@ -9978,16 +10309,22 @@ private: // now. if (S.getLangOpts().CPlusPlus14 && FunDecl->getReturnType()->isUndeducedType() && - S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) + S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) { + HasComplained |= Complain; + return false; + } + + if (!S.checkAddressOfFunctionIsAvailable(FunDecl)) return false; QualType ResultTy; if (Context.hasSameUnqualifiedType(TargetFunctionType, FunDecl->getType()) || S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType, - ResultTy)) { - Matches.push_back(std::make_pair(CurAccessFunPair, - cast<FunctionDecl>(FunDecl->getCanonicalDecl()))); + ResultTy) || + (!S.getLangOpts().CPlusPlus && TargetType->isVoidPointerType())) { + Matches.push_back(std::make_pair( + CurAccessFunPair, cast<FunctionDecl>(FunDecl->getCanonicalDecl()))); FoundNonTemplateFunction = true; return true; } @@ -10061,7 +10398,8 @@ private: Matches[0].first = Matches[Result - MatchesCopy.begin()].first; Matches[0].second = cast<FunctionDecl>(*Result); Matches.resize(1); - } + } else + HasComplained |= Complain; } void EliminateAllTemplateMatches() { @@ -10072,11 +10410,15 @@ private: ++I; else { Matches[I] = Matches[--N]; - Matches.set_size(N); + Matches.resize(N); } } } + void EliminateSuboptimalCudaMatches() { + S.EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(S.CurContext), Matches); + } + public: void ComplainNoMatchesFound() const { assert(Matches.empty()); @@ -10084,7 +10426,8 @@ public: << OvlExpr->getName() << TargetFunctionType << OvlExpr->getSourceRange(); if (FailedCandidates.empty()) - S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType, + /*TakingAddress=*/true); else { // We have some deduction failure messages. Use them to diagnose // the function templates, and diagnose the non-template candidates @@ -10094,7 +10437,9 @@ public: I != IEnd; ++I) if (FunctionDecl *Fun = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl())) - S.NoteOverloadCandidate(Fun, TargetFunctionType); + if (!functionHasPassObjectSizeParams(Fun)) + S.NoteOverloadCandidate(Fun, TargetFunctionType, + /*TakingAddress=*/true); FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart()); } } @@ -10132,7 +10477,8 @@ public: S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous) << OvlExpr->getName() << OvlExpr->getSourceRange(); - S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType, + /*TakingAddress=*/true); } bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); } @@ -10178,13 +10524,14 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, Complain); int NumMatches = Resolver.getNumMatches(); FunctionDecl *Fn = nullptr; - if (NumMatches == 0 && Complain) { + bool ShouldComplain = Complain && !Resolver.hasComplained(); + if (NumMatches == 0 && ShouldComplain) { if (Resolver.IsInvalidFormOfPointerToMemberFunction()) Resolver.ComplainIsInvalidFormOfPointerToMemberFunction(); else Resolver.ComplainNoMatchesFound(); } - else if (NumMatches > 1 && Complain) + else if (NumMatches > 1 && ShouldComplain) Resolver.ComplainMultipleMatchesFound(); else if (NumMatches == 1) { Fn = Resolver.getMatchingFunctionDecl(); @@ -10229,7 +10576,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, return nullptr; TemplateArgumentListInfo ExplicitTemplateArgs; - ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); + ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs); TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc()); // Look through all of the overloaded functions, searching for one @@ -10303,7 +10650,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, // returns true if 'complain' is set. bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, bool doFunctionPointerConverion, - bool complain, const SourceRange& OpRangeForComplaining, + bool complain, SourceRange OpRangeForComplaining, QualType DestTypeForComplaining, unsigned DiagIDForComplaining) { assert(SrcExpr.get()->getType() == Context.OverloadTy); @@ -10678,8 +11025,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // casts and such from the call, we don't really care. ExprResult NewFn = ExprError(); if ((*R.begin())->isCXXClassMember()) - NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, - R, ExplicitTemplateArgs); + NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, + ExplicitTemplateArgs, S); else if (ExplicitTemplateArgs || TemplateKWLoc.isValid()) NewFn = SemaRef.BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, ExplicitTemplateArgs); @@ -10749,6 +11096,8 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, CallExpr *CE = new (Context) CallExpr( Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc); CE->setTypeDependent(true); + CE->setValueDependent(true); + CE->setInstantiationDependent(true); *Result = CE; return true; } @@ -10800,9 +11149,23 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, if (!Recovery.isInvalid()) return Recovery; - SemaRef.Diag(Fn->getLocStart(), - diag::err_ovl_no_viable_function_in_call) - << ULE->getName() << Fn->getSourceRange(); + // If the user passes in a function that we can't take the address of, we + // generally end up emitting really bad error messages. Here, we attempt to + // emit better ones. + for (const Expr *Arg : Args) { + if (!Arg->getType()->isFunctionType()) + continue; + if (auto *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts())) { + auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()); + if (FD && + !SemaRef.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, + Arg->getExprLoc())) + return ExprError(); + } + } + + SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_no_viable_function_in_call) + << ULE->getName() << Fn->getSourceRange(); CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args); break; } @@ -10875,8 +11238,7 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) { /// /// \param OpLoc The location of the operator itself (e.g., '*'). /// -/// \param OpcIn The UnaryOperator::Opcode that describes this -/// operator. +/// \param Opc The UnaryOperatorKind that describes this operator. /// /// \param Fns The set of non-member functions that will be /// considered by overload resolution. The caller needs to build this @@ -10887,11 +11249,9 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) { /// /// \param Input The input argument. ExprResult -Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, +Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *Input) { - UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn); - OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc); assert(Op != OO_None && "Invalid opcode for overloaded unary operator"); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); @@ -11062,8 +11422,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, /// /// \param OpLoc The location of the operator itself (e.g., '+'). /// -/// \param OpcIn The BinaryOperator::Opcode that describes this -/// operator. +/// \param Opc The BinaryOperatorKind that describes this operator. /// /// \param Fns The set of non-member functions that will be /// considered by overload resolution. The caller needs to build this @@ -11076,13 +11435,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, /// \param RHS Right-hand argument. ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, - unsigned OpcIn, + BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *LHS, Expr *RHS) { Expr *Args[2] = { LHS, RHS }; LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple - BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn); OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); @@ -11565,10 +11923,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, << (qualsString.find(' ') == std::string::npos ? 1 : 2); } - if (resultType->isMemberPointerType()) - if (Context.getTargetInfo().getCXXABI().isMicrosoft()) - RequireCompleteType(LParenLoc, resultType, 0); - CXXMemberCallExpr *call = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, resultType, valueKind, RParenLoc); @@ -11767,18 +12121,39 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (CheckFunctionCall(Method, TheCall, Proto)) return ExprError(); + // In the case the method to call was not selected by the overloading + // resolution process, we still need to handle the enable_if attribute. Do + // that here, so it will not hide previous -- and more relevant -- errors + if (isa<MemberExpr>(NakedMemExpr)) { + if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) { + Diag(MemExprE->getLocStart(), + diag::err_ovl_no_viable_member_function_in_call) + << Method << Method->getSourceRange(); + Diag(Method->getLocation(), + diag::note_ovl_candidate_disabled_by_enable_if_attr) + << Attr->getCond()->getSourceRange() << Attr->getMessage(); + return ExprError(); + } + } + if ((isa<CXXConstructorDecl>(CurContext) || isa<CXXDestructorDecl>(CurContext)) && TheCall->getMethodDecl()->isPure()) { const CXXMethodDecl *MD = TheCall->getMethodDecl(); - if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts())) { - Diag(MemExpr->getLocStart(), + if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts()) && + MemExpr->performsVirtualDispatch(getLangOpts())) { + Diag(MemExpr->getLocStart(), diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor) << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext) << MD->getParent()->getDeclName(); Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName(); + if (getLangOpts().AppleKext) + Diag(MemExpr->getLocStart(), + diag::note_pure_qualified_call_kext) + << MD->getParent()->getDeclName() + << MD->getDeclName(); } } return MaybeBindToTemporary(TheCall); @@ -12267,13 +12642,14 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, /// otherwise CallExpr is set to ExprError() and some non-success value /// is returned. Sema::ForRangeStatus -Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc, - SourceLocation RangeLoc, VarDecl *Decl, - BeginEndFunction BEF, +Sema::BuildForRangeBeginEndCall(SourceLocation Loc, + SourceLocation RangeLoc, const DeclarationNameInfo &NameInfo, LookupResult &MemberLookup, OverloadCandidateSet *CandidateSet, Expr *Range, ExprResult *CallExpr) { + Scope *S = nullptr; + CandidateSet->clear(); if (!MemberLookup.empty()) { ExprResult MemberRef = @@ -12282,18 +12658,14 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/nullptr, MemberLookup, - /*TemplateArgs=*/nullptr); + /*TemplateArgs=*/nullptr, S); if (MemberRef.isInvalid()) { *CallExpr = ExprError(); - Diag(Range->getLocStart(), diag::note_in_for_range) - << RangeLoc << BEF << Range->getType(); return FRS_DiagnosticIssued; } *CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, None, Loc, nullptr); if (CallExpr->isInvalid()) { *CallExpr = ExprError(); - Diag(Range->getLocStart(), diag::note_in_for_range) - << RangeLoc << BEF << Range->getType(); return FRS_DiagnosticIssued; } } else { @@ -12324,8 +12696,6 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc, /*AllowTypoCorrection=*/false); if (CallExpr->isInvalid() || OverloadResult != OR_Success) { *CallExpr = ExprError(); - Diag(Range->getLocStart(), diag::note_in_for_range) - << RangeLoc << BEF << Range->getType(); return FRS_DiagnosticIssued; } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp index fec9748..e5d51f1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp @@ -44,17 +44,76 @@ using namespace sema; namespace { // Basically just a very focused copy of TreeTransform. - template <class T> struct Rebuilder { + struct Rebuilder { Sema &S; - Rebuilder(Sema &S) : S(S) {} + unsigned MSPropertySubscriptCount; + typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy; + const SpecificRebuilderRefTy &SpecificCallback; + Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback) + : S(S), MSPropertySubscriptCount(0), + SpecificCallback(SpecificCallback) {} + + Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) { + // Fortunately, the constraint that we're rebuilding something + // with a base limits the number of cases here. + if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) + return refExpr; + + if (refExpr->isExplicitProperty()) { + return new (S.Context) ObjCPropertyRefExpr( + refExpr->getExplicitProperty(), refExpr->getType(), + refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); + } + return new (S.Context) ObjCPropertyRefExpr( + refExpr->getImplicitPropertyGetter(), + refExpr->getImplicitPropertySetter(), refExpr->getType(), + refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0)); + } + Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) { + assert(refExpr->getBaseExpr()); + assert(refExpr->getKeyExpr()); + + return new (S.Context) ObjCSubscriptRefExpr( + SpecificCallback(refExpr->getBaseExpr(), 0), + SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(), + refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(), + refExpr->getRBracket()); + } + Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) { + assert(refExpr->getBaseExpr()); - T &getDerived() { return static_cast<T&>(*this); } + return new (S.Context) MSPropertyRefExpr( + SpecificCallback(refExpr->getBaseExpr(), 0), + refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(), + refExpr->getValueKind(), refExpr->getQualifierLoc(), + refExpr->getMemberLoc()); + } + Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) { + assert(refExpr->getBase()); + assert(refExpr->getIdx()); + + auto *NewBase = rebuild(refExpr->getBase()); + ++MSPropertySubscriptCount; + return new (S.Context) MSPropertySubscriptExpr( + NewBase, + SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount), + refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(), + refExpr->getRBracketLoc()); + } Expr *rebuild(Expr *e) { // Fast path: nothing to look through. - if (typename T::specific_type *specific - = dyn_cast<typename T::specific_type>(e)) - return getDerived().rebuildSpecific(specific); + if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e)) + return rebuildObjCPropertyRefExpr(PRE); + if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e)) + return rebuildObjCSubscriptRefExpr(SRE); + if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e)) + return rebuildMSPropertyRefExpr(MSPRE); + if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e)) + return rebuildMSPropertySubscriptExpr(MSPSE); // Otherwise, we should look through and rebuild anything that // IgnoreParens would. @@ -125,72 +184,6 @@ namespace { } }; - struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> { - Expr *NewBase; - ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) - : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {} - - typedef ObjCPropertyRefExpr specific_type; - Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { - // Fortunately, the constraint that we're rebuilding something - // with a base limits the number of cases here. - assert(refExpr->isObjectReceiver()); - - if (refExpr->isExplicitProperty()) { - return new (S.Context) - ObjCPropertyRefExpr(refExpr->getExplicitProperty(), - refExpr->getType(), refExpr->getValueKind(), - refExpr->getObjectKind(), refExpr->getLocation(), - NewBase); - } - return new (S.Context) - ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), - refExpr->getImplicitPropertySetter(), - refExpr->getType(), refExpr->getValueKind(), - refExpr->getObjectKind(),refExpr->getLocation(), - NewBase); - } - }; - - struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> { - Expr *NewBase; - Expr *NewKeyExpr; - ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr) - : Rebuilder<ObjCSubscriptRefRebuilder>(S), - NewBase(newBase), NewKeyExpr(newKeyExpr) {} - - typedef ObjCSubscriptRefExpr specific_type; - Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) { - assert(refExpr->getBaseExpr()); - assert(refExpr->getKeyExpr()); - - return new (S.Context) - ObjCSubscriptRefExpr(NewBase, - NewKeyExpr, - refExpr->getType(), refExpr->getValueKind(), - refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(), - refExpr->setAtIndexMethodDecl(), - refExpr->getRBracket()); - } - }; - - struct MSPropertyRefRebuilder : Rebuilder<MSPropertyRefRebuilder> { - Expr *NewBase; - MSPropertyRefRebuilder(Sema &S, Expr *newBase) - : Rebuilder<MSPropertyRefRebuilder>(S), NewBase(newBase) {} - - typedef MSPropertyRefExpr specific_type; - Expr *rebuildSpecific(MSPropertyRefExpr *refExpr) { - assert(refExpr->getBaseExpr()); - - return new (S.Context) - MSPropertyRefExpr(NewBase, refExpr->getPropertyDecl(), - refExpr->isArrow(), refExpr->getType(), - refExpr->getValueKind(), refExpr->getQualifierLoc(), - refExpr->getMemberLoc()); - } - }; - class PseudoOpBuilder { public: Sema &S; @@ -236,7 +229,7 @@ namespace { } /// Return true if assignments have a non-void result. - bool CanCaptureValue(Expr *exp) { + static bool CanCaptureValue(Expr *exp) { if (exp->isGLValue()) return true; QualType ty = exp->getType(); @@ -252,6 +245,20 @@ namespace { virtual ExprResult buildGet() = 0; virtual ExprResult buildSet(Expr *, SourceLocation, bool captureSetValueAsResult) = 0; + /// \brief Should the result of an assignment be the formal result of the + /// setter call or the value that was passed to the setter? + /// + /// Different pseudo-object language features use different language rules + /// for this. + /// The default is to use the set value. Currently, this affects the + /// behavior of simple assignments, compound assignments, and prefix + /// increment and decrement. + /// Postfix increment and decrement always use the getter result as the + /// expression result. + /// + /// If this method returns true, and the set value isn't capturable for + /// some reason, the result of the expression will be void. + virtual bool captureSetValueAsResult() const { return true; } }; /// A PseudoOpBuilder for Objective-C \@properties. @@ -328,15 +335,25 @@ namespace { class MSPropertyOpBuilder : public PseudoOpBuilder { MSPropertyRefExpr *RefExpr; + OpaqueValueExpr *InstanceBase; + SmallVector<Expr *, 4> CallArgs; + + MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E); public: MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), - RefExpr(refExpr) {} + RefExpr(refExpr), InstanceBase(nullptr) {} + MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr) + : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), + InstanceBase(nullptr) { + RefExpr = getBaseMSProperty(refExpr); + } Expr *rebuildAndCaptureObject(Expr *) override; ExprResult buildGet() override; ExprResult buildSet(Expr *op, SourceLocation, bool) override; + bool captureSetValueAsResult() const override { return false; } }; } @@ -406,19 +423,27 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, BinaryOperatorKind opcode, Expr *LHS, Expr *RHS) { assert(BinaryOperator::isAssignmentOp(opcode)); - - // Recover from user error - if (isa<UnresolvedLookupExpr>(RHS)) - return ExprError(); Expr *syntacticLHS = rebuildAndCaptureObject(LHS); OpaqueValueExpr *capturedRHS = capture(RHS); + // In some very specific cases, semantic analysis of the RHS as an + // expression may require it to be rewritten. In these cases, we + // cannot safely keep the OVE around. Fortunately, we don't really + // need to: we don't use this particular OVE in multiple places, and + // no clients rely that closely on matching up expressions in the + // semantic expression with expressions from the syntactic form. + Expr *semanticRHS = capturedRHS; + if (RHS->hasPlaceholderType() || isa<InitListExpr>(RHS)) { + semanticRHS = RHS; + Semantics.pop_back(); + } + Expr *syntactic; ExprResult result; if (opcode == BO_Assign) { - result = capturedRHS; + result = semanticRHS; syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, opcode, capturedRHS->getType(), capturedRHS->getValueKind(), @@ -430,8 +455,7 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, // Build an ordinary, non-compound operation. BinaryOperatorKind nonCompound = BinaryOperator::getOpForCompoundAssignment(opcode); - result = S.BuildBinOp(Sc, opcLoc, nonCompound, - opLHS.get(), capturedRHS); + result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS); if (result.isInvalid()) return ExprError(); syntactic = @@ -446,9 +470,12 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, // The result of the assignment, if not void, is the value set into // the l-value. - result = buildSet(result.get(), opcLoc, /*captureSetValueAsResult*/ true); + result = buildSet(result.get(), opcLoc, captureSetValueAsResult()); if (result.isInvalid()) return ExprError(); addSemanticExpr(result.get()); + if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() && + (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) + setResultToLastSemantic(); return complete(syntactic); } @@ -490,9 +517,14 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, // Store that back into the result. The value stored is the result // of a prefix operation. - result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode)); + result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) && + captureSetValueAsResult()); if (result.isInvalid()) return ExprError(); addSemanticExpr(result.get()); + if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() && + !result.get()->getType()->isVoidType() && + (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) + setResultToLastSemantic(); UnaryOperator *syntactic = new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, @@ -666,9 +698,9 @@ Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { // form to use the OVE as its base. if (RefExpr->isObjectReceiver()) { InstanceReceiver = capture(RefExpr->getBase()); - - syntacticBase = - ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); + syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * { + return InstanceReceiver; + }).rebuild(syntacticBase); } if (ObjCPropertyRefExpr * @@ -745,16 +777,6 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, op = opResult.get(); assert(op && "successful assignment left argument invalid?"); } - else if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(op)) { - Expr *Initializer = OVE->getSourceExpr(); - // passing C++11 style initialized temporaries to objc++ properties - // requires special treatment by removing OpaqueValueExpr so type - // conversion takes place and adding the OpaqueValueExpr later on. - if (isa<InitListExpr>(Initializer) && - Initializer->getType()->isVoidType()) { - op = Initializer; - } - } } // Arguments. @@ -996,11 +1018,19 @@ Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { // form to use the OVE as its base expression. InstanceBase = capture(RefExpr->getBaseExpr()); InstanceKey = capture(RefExpr->getKeyExpr()); - + syntacticBase = - ObjCSubscriptRefRebuilder(S, InstanceBase, - InstanceKey).rebuild(syntacticBase); - + Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * { + switch (Idx) { + case 0: + return InstanceBase; + case 1: + return InstanceKey; + default: + llvm_unreachable("Unexpected index for ObjCSubscriptExpr"); + } + }).rebuild(syntacticBase); + return syntacticBase; } @@ -1402,11 +1432,30 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, // MSVC __declspec(property) references //===----------------------------------------------------------------------===// -Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { - Expr *NewBase = capture(RefExpr->getBaseExpr()); +MSPropertyRefExpr * +MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) { + CallArgs.insert(CallArgs.begin(), E->getIdx()); + Expr *Base = E->getBase()->IgnoreParens(); + while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) { + CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx()); + Base = MSPropSubscript->getBase()->IgnoreParens(); + } + return cast<MSPropertyRefExpr>(Base); +} - syntacticBase = - MSPropertyRefRebuilder(S, NewBase).rebuild(syntacticBase); +Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { + InstanceBase = capture(RefExpr->getBaseExpr()); + std::for_each(CallArgs.begin(), CallArgs.end(), + [this](Expr *&Arg) { Arg = capture(Arg); }); + syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * { + switch (Idx) { + case 0: + return InstanceBase; + default: + assert(Idx <= CallArgs.size()); + return CallArgs[Idx - 1]; + } + }).rebuild(syntacticBase); return syntacticBase; } @@ -1423,10 +1472,10 @@ ExprResult MSPropertyOpBuilder::buildGet() { GetterName.setIdentifier(II, RefExpr->getMemberLoc()); CXXScopeSpec SS; SS.Adopt(RefExpr->getQualifierLoc()); - ExprResult GetterExpr = S.ActOnMemberAccessExpr( - S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), - RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), - GetterName, nullptr); + ExprResult GetterExpr = + S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(), + RefExpr->isArrow() ? tok::arrow : tok::period, SS, + SourceLocation(), GetterName, nullptr); if (GetterExpr.isInvalid()) { S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_accessor) << 0 /* getter */ @@ -1434,9 +1483,8 @@ ExprResult MSPropertyOpBuilder::buildGet() { return ExprError(); } - MultiExprArg ArgExprs; return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(), - RefExpr->getSourceRange().getBegin(), ArgExprs, + RefExpr->getSourceRange().getBegin(), CallArgs, RefExpr->getSourceRange().getEnd()); } @@ -1453,10 +1501,10 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, SetterName.setIdentifier(II, RefExpr->getMemberLoc()); CXXScopeSpec SS; SS.Adopt(RefExpr->getQualifierLoc()); - ExprResult SetterExpr = S.ActOnMemberAccessExpr( - S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), - RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), - SetterName, nullptr); + ExprResult SetterExpr = + S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(), + RefExpr->isArrow() ? tok::arrow : tok::period, SS, + SourceLocation(), SetterName, nullptr); if (SetterExpr.isInvalid()) { S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_accessor) << 1 /* setter */ @@ -1464,7 +1512,8 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, return ExprError(); } - SmallVector<Expr*, 1> ArgExprs; + SmallVector<Expr*, 4> ArgExprs; + ArgExprs.append(CallArgs.begin(), CallArgs.end()); ArgExprs.push_back(op); return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(), RefExpr->getSourceRange().getBegin(), ArgExprs, @@ -1490,6 +1539,10 @@ ExprResult Sema::checkPseudoObjectRValue(Expr *E) { = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { MSPropertyOpBuilder builder(*this, refExpr); return builder.buildRValueOperation(E); + } else if (MSPropertySubscriptExpr *RefExpr = + dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { + MSPropertyOpBuilder Builder(*this, RefExpr); + return Builder.buildRValueOperation(E); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1516,6 +1569,10 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { MSPropertyOpBuilder builder(*this, refExpr); return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); + } else if (MSPropertySubscriptExpr *RefExpr + = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { + MSPropertyOpBuilder Builder(*this, RefExpr); + return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1547,8 +1604,12 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); } else if (MSPropertyRefExpr *refExpr = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { - MSPropertyOpBuilder builder(*this, refExpr); - return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); + MSPropertyOpBuilder builder(*this, refExpr); + return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); + } else if (MSPropertySubscriptExpr *RefExpr + = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) { + MSPropertyOpBuilder Builder(*this, RefExpr); + return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); } else { llvm_unreachable("unknown pseudo-object kind!"); } @@ -1558,29 +1619,11 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, /// values. Basically, undo the behavior of rebuildAndCaptureObject. /// This should never operate in-place. static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { - Expr *opaqueRef = E->IgnoreParens(); - if (ObjCPropertyRefExpr *refExpr - = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { - // Class and super property references don't have opaque values in them. - if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) - return E; - - assert(refExpr->isObjectReceiver() && "Unknown receiver kind?"); - OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase()); - return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); - } else if (ObjCSubscriptRefExpr *refExpr - = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { - OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); - OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr()); - return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), - keyOVE->getSourceExpr()).rebuild(E); - } else if (MSPropertyRefExpr *refExpr - = dyn_cast<MSPropertyRefExpr>(opaqueRef)) { - OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); - return MSPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); - } else { - llvm_unreachable("unknown pseudo-object kind!"); - } + return Rebuilder(S, + [=](Expr *E, unsigned) -> Expr * { + return cast<OpaqueValueExpr>(E)->getSourceExpr(); + }) + .rebuild(E); } /// Given a pseudo-object expression, recreate what it looks like diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index c4f6fd8..e1b1a47 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -195,7 +195,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (isUnevaluatedContext()) return; - SourceLocation ExprLoc = E->IgnoreParens()->getExprLoc(); + SourceLocation ExprLoc = E->IgnoreParenImpCasts()->getExprLoc(); // In most cases, we don't want to warn if the expression is written in a // macro body, or if the macro comes from a system header. If the offending // expression is a call to a function with the warn_unused_result attribute, @@ -218,6 +218,15 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (isa<StmtExpr>(E) && Loc.isMacroID()) return; + // Check if this is the UNREFERENCED_PARAMETER from the Microsoft headers. + // That macro is frequently used to suppress "unused parameter" warnings, + // but its implementation makes clang's -Wunused-value fire. Prevent this. + if (isa<ParenExpr>(E->IgnoreImpCasts()) && Loc.isMacroID()) { + SourceLocation SpellLoc = Loc; + if (findMacroSpelling(SpellLoc, "UNREFERENCED_PARAMETER")) + return; + } + // Okay, we have an unused result. Depending on what the base expression is, // we might want to make a more specific diagnostic. Check for one of these // cases now. @@ -483,13 +492,6 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - // If the condition was invalid, discard the if statement. We could recover - // better by replacing it with a valid expr, but don't do that yet. - if (!CondVal.get() && !CondVar) { - getCurFunction()->setHasDroppedStmt(); - return StmtError(); - } - ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = nullptr; @@ -497,22 +499,23 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, ConditionVar = cast<VarDecl>(CondVar); CondResult = CheckConditionVariable(ConditionVar, IfLoc, true); CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc); - if (CondResult.isInvalid()) - return StmtError(); } Expr *ConditionExpr = CondResult.getAs<Expr>(); - if (!ConditionExpr) - return StmtError(); + if (ConditionExpr) { + DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(thenStmt); + if (!elseStmt) { + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, + diag::warn_empty_if_body); + } - if (!elseStmt) { - DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); + DiagnoseUnusedExprResult(elseStmt); + } else { + // Create a dummy Expr for the condition for error recovery + ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(), + Context.BoolTy, VK_RValue); } - DiagnoseUnusedExprResult(elseStmt); - return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, thenStmt, ElseLoc, elseStmt); } @@ -698,8 +701,6 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, 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())) { @@ -711,7 +712,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, } } - if (FlagType) { + if (ED->hasAttr<FlagEnumAttr>()) { return !S.IsValueInFlagEnum(ED, Val, false); } else { while (EI != EIEnd && EI->first < Val) @@ -1349,7 +1350,7 @@ namespace { }; // end class DeclExtractor - // DeclMatcher checks to see if the decls are used in a non-evauluated + // DeclMatcher checks to see if the decls are used in a non-evaluated // context. class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> { llvm::SmallPtrSetImpl<VarDecl*> &Decls; @@ -1705,11 +1706,10 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { // If we have a forward-declared type, we can't do this check. // Under ARC, it is an error not to have a forward-declared class. if (iface && - RequireCompleteType(forLoc, QualType(objectType, 0), - getLangOpts().ObjCAutoRefCount - ? diag::err_arc_collection_forward - : 0, - collection)) { + (getLangOpts().ObjCAutoRefCount + ? RequireCompleteType(forLoc, QualType(objectType, 0), + diag::err_arc_collection_forward, collection) + : !isCompleteType(forLoc, QualType(objectType, 0)))) { // Otherwise, if we have any useful type information, check that // the type declares the appropriate method. } else if (iface || !objectType->qual_empty()) { @@ -1867,13 +1867,19 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, } namespace { +// An enum to represent whether something is dealing with a call to begin() +// or a call to end() in a range-based for loop. +enum BeginEndFunction { + BEF_begin, + BEF_end +}; /// Produce a note indicating which begin/end function was implicitly called /// by a C++11 for-range statement. This is often not obvious from the code, /// nor from the diagnostics produced when analysing the implicit expressions /// required in a for-range statement. void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, - Sema::BeginEndFunction BEF) { + BeginEndFunction BEF) { CallExpr *CE = dyn_cast<CallExpr>(E); if (!CE) return; @@ -1931,10 +1937,11 @@ static bool ObjCEnumerationCollection(Expr *Collection) { /// /// The body of the loop is not available yet, since it cannot be analysed until /// we have determined the type of the for-range-declaration. -StmtResult -Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, - Stmt *First, SourceLocation ColonLoc, Expr *Range, - SourceLocation RParenLoc, BuildForRangeKind Kind) { +StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, + SourceLocation CoawaitLoc, Stmt *First, + SourceLocation ColonLoc, Expr *Range, + SourceLocation RParenLoc, + BuildForRangeKind Kind) { if (!First) return StmtError(); @@ -1956,6 +1963,13 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, return StmtError(); } + // Coroutines: 'for co_await' implicitly co_awaits its range. + if (CoawaitLoc.isValid()) { + ExprResult Coawait = ActOnCoawaitExpr(S, CoawaitLoc, Range); + if (Coawait.isInvalid()) return StmtError(); + Range = Coawait.get(); + } + // Build auto && __range = range-init SourceLocation RangeLoc = Range->getLocStart(); VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc, @@ -1977,7 +1991,7 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, return StmtError(); } - return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(), + return BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc, RangeDecl.get(), /*BeginEndDecl=*/nullptr, /*Cond=*/nullptr, /*Inc=*/nullptr, DS, RParenLoc, Kind); } @@ -1991,7 +2005,7 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, /// BeginExpr and EndExpr are set and FRS_Success is returned on success; /// CandidateSet and BEF are set and some non-success value is returned on /// failure. -static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S, +static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, QualType RangeType, VarDecl *BeginVar, @@ -2000,7 +2014,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S, OverloadCandidateSet *CandidateSet, ExprResult *BeginExpr, ExprResult *EndExpr, - Sema::BeginEndFunction *BEF) { + BeginEndFunction *BEF) { DeclarationNameInfo BeginNameInfo( &SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc); DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"), @@ -2021,7 +2035,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S, if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { SourceLocation RangeLoc = BeginVar->getLocation(); - *BEF = BeginMemberLookup.empty() ? Sema::BEF_end : Sema::BEF_begin; + *BEF = BeginMemberLookup.empty() ? BEF_end : BEF_begin; SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch) << RangeLoc << BeginRange->getType() << *BEF; @@ -2035,29 +2049,35 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S, } - *BEF = Sema::BEF_begin; + *BEF = BEF_begin; Sema::ForRangeStatus RangeStatus = - SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, BeginVar, - Sema::BEF_begin, BeginNameInfo, + SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo, BeginMemberLookup, CandidateSet, BeginRange, BeginExpr); - if (RangeStatus != Sema::FRS_Success) + if (RangeStatus != Sema::FRS_Success) { + if (RangeStatus == Sema::FRS_DiagnosticIssued) + SemaRef.Diag(BeginRange->getLocStart(), diag::note_in_for_range) + << ColonLoc << BEF_begin << BeginRange->getType(); return RangeStatus; + } if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc, diag::err_for_range_iter_deduction_failure)) { NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF); return Sema::FRS_DiagnosticIssued; } - *BEF = Sema::BEF_end; + *BEF = BEF_end; RangeStatus = - SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, EndVar, - Sema::BEF_end, EndNameInfo, + SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo, EndMemberLookup, CandidateSet, EndRange, EndExpr); - if (RangeStatus != Sema::FRS_Success) + if (RangeStatus != Sema::FRS_Success) { + if (RangeStatus == Sema::FRS_DiagnosticIssued) + SemaRef.Diag(EndRange->getLocStart(), diag::note_in_for_range) + << ColonLoc << BEF_end << EndRange->getType(); return RangeStatus; + } if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc, diag::err_for_range_iter_deduction_failure)) { NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF); @@ -2071,6 +2091,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S, /// and emit no diagnostics. static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, SourceLocation ForLoc, + SourceLocation CoawaitLoc, Stmt *LoopVarDecl, SourceLocation ColonLoc, Expr *Range, @@ -2086,10 +2107,9 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, if (AdjustedRange.isInvalid()) return StmtResult(); - StmtResult SR = - SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc, - AdjustedRange.get(), RParenLoc, - Sema::BFRK_Check); + StmtResult SR = SemaRef.ActOnCXXForRangeStmt( + S, ForLoc, CoawaitLoc, LoopVarDecl, ColonLoc, AdjustedRange.get(), + RParenLoc, Sema::BFRK_Check); if (SR.isInvalid()) return StmtResult(); } @@ -2099,8 +2119,8 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, // case there are any other (non-fatal) problems with it. SemaRef.Diag(RangeLoc, diag::err_for_range_dereference) << Range->getType() << FixItHint::CreateInsertion(RangeLoc, "*"); - return SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc, - AdjustedRange.get(), RParenLoc, + return SemaRef.ActOnCXXForRangeStmt(S, ForLoc, CoawaitLoc, LoopVarDecl, + ColonLoc, AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild); } @@ -2122,10 +2142,20 @@ struct InvalidateOnErrorScope { /// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. StmtResult -Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, +Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, + SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc, BuildForRangeKind Kind) { + // FIXME: This should not be used during template instantiation. We should + // pick up the set of unqualified lookup results for the != and + operators + // in the initial parse. + // + // Testcase (accepts-invalid): + // template<typename T> void f() { for (auto x : T()) {} } + // namespace N { struct X { X begin(); X end(); int operator*(); }; } + // bool operator!=(N::X, N::X); void operator++(N::X); + // void g() { f<N::X>(); } Scope *S = getCurScope(); DeclStmt *RangeDS = cast<DeclStmt>(RangeDecl); @@ -2225,9 +2255,9 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, } else { OverloadCandidateSet CandidateSet(RangeLoc, OverloadCandidateSet::CSK_Normal); - Sema::BeginEndFunction BEFFailure; + BeginEndFunction BEFFailure; ForRangeStatus RangeStatus = - BuildNonArrayForRange(*this, S, BeginRangeRef.get(), + BuildNonArrayForRange(*this, BeginRangeRef.get(), EndRangeRef.get(), RangeType, BeginVar, EndVar, ColonLoc, &CandidateSet, &BeginExpr, &EndExpr, &BEFFailure); @@ -2252,6 +2282,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, // If building the range failed, try dereferencing the range expression // unless a diagnostic was issued or the end function is problematic. StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc, + CoawaitLoc, LoopVarDecl, ColonLoc, Range, RangeLoc, RParenLoc); @@ -2322,7 +2353,10 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, return StmtError(); IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get()); - IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); + if (!IncrExpr.isInvalid() && CoawaitLoc.isValid()) + IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get()); + if (!IncrExpr.isInvalid()) + IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); if (IncrExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 2 << BeginRangeRef.get()->getType() ; @@ -2361,7 +2395,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, return new (Context) CXXForRangeStmt( RangeDS, cast_or_null<DeclStmt>(BeginEndDecl.get()), NotEqExpr.get(), - IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, ColonLoc, RParenLoc); + IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, CoawaitLoc, + ColonLoc, RParenLoc); } /// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach @@ -2919,6 +2954,9 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (CurCap->HasImplicitReturnType || NRVOCandidate) FunctionScopes.back()->Returns.push_back(Result); + if (FunctionScopes.back()->FirstReturnLoc.isInvalid()) + FunctionScopes.back()->FirstReturnLoc = ReturnLoc; + return Result; } @@ -2989,14 +3027,9 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, // statement with a non-type-dependent operand. assert(AT->isDeduced() && "should have deduced to dependent type"); return false; - } else if (RetExpr) { - // If the deduction is for a return statement and the initializer is - // a braced-init-list, the program is ill-formed. - if (isa<InitListExpr>(RetExpr)) { - Diag(RetExpr->getExprLoc(), diag::err_auto_fn_return_init_list); - return true; - } + } + if (RetExpr) { // Otherwise, [...] deduce a value for U using the rules of template // argument deduction. DeduceAutoResult DAR = DeduceAutoType(OrigResultType, RetExpr, Deduced); @@ -3035,8 +3068,11 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, // the program is ill-formed. if (AT->isDeduced() && !FD->isInvalidDecl()) { AutoType *NewAT = Deduced->getContainedAutoType(); - if (!FD->isDependentContext() && - !Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) { + CanQualType OldDeducedType = Context.getCanonicalFunctionResultType( + AT->getDeducedType()); + CanQualType NewDeducedType = Context.getCanonicalFunctionResultType( + NewAT->getDeducedType()); + if (!FD->isDependentContext() && OldDeducedType != NewDeducedType) { const LambdaScopeInfo *LambdaSI = getCurLambda(); if (LambdaSI && LambdaSI->HasImplicitReturnType) { Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) @@ -3179,7 +3215,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } // return (some void expression); is legal in C++. else if (D != diag::ext_return_has_void_expr || - !getLangOpts().CPlusPlus) { + !getLangOpts().CPlusPlus) { NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); int FunctionKind = 0; @@ -3287,6 +3323,9 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (Result->getNRVOCandidate()) FunctionScopes.back()->Returns.push_back(Result); + if (FunctionScopes.back()->FirstReturnLoc.isInvalid()) + FunctionScopes.back()->FirstReturnLoc = ReturnLoc; + return Result; } @@ -3512,16 +3551,14 @@ public: 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); + bool operator()(const CXXBaseSpecifier *S, CXXBasePath &) { if (S->getAccessSpecifier() == AccessSpecifier::AS_public) { - CatchHandlerType Check(S->getType(), PBOT.CheckAgainstPointer); - auto M = PBOT.TypesToCheck; + CatchHandlerType Check(S->getType(), CheckAgainstPointer); + auto M = TypesToCheck; auto I = M.find(Check); if (I != M.end()) { - PBOT.FoundHandler = I->second; - PBOT.FoundHandlerType = PBOT.Ctx.getCanonicalType(S->getType()); + FoundHandler = I->second; + FoundHandlerType = Ctx.getCanonicalType(S->getType()); return true; } } @@ -3589,8 +3626,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, CXXBasePaths Paths; Paths.setOrigin(RD); CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer()); - if (RD->lookupInBases(CatchTypePublicBases::FindPublicBasesOfType, &CTPB, - Paths)) { + if (RD->lookupInBases(CTPB, Paths)) { const CXXCatchStmt *Problem = CTPB.getFoundHandler(); if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) { Diag(H->getExceptionDecl()->getTypeSpecStartLoc(), @@ -3766,11 +3802,10 @@ static void buildCapturedStmtCaptureList( continue; } - assert(Cap->isReferenceCapture() && - "non-reference capture not yet implemented"); - Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), - CapturedStmt::VCK_ByRef, + Cap->isReferenceCapture() + ? CapturedStmt::VCK_ByRef + : CapturedStmt::VCK_ByCopy, Cap->getVariable())); CaptureInits.push_back(Cap->getInitExpr()); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp index 8e3e89f..0d6e0f8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp @@ -107,6 +107,37 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) { return false; } +/// \brief Returns true if given expression is not compatible with inline +/// assembly's memory constraint; false otherwise. +static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E, + TargetInfo::ConstraintInfo &Info, + bool is_input_expr) { + enum { + ExprBitfield = 0, + ExprVectorElt, + ExprGlobalRegVar, + ExprSafeType + } EType = ExprSafeType; + + // Bitfields, vector elements and global register variables are not + // compatible. + if (E->refersToBitField()) + EType = ExprBitfield; + else if (E->refersToVectorElement()) + EType = ExprVectorElt; + else if (E->refersToGlobalRegisterVar()) + EType = ExprGlobalRegVar; + + if (EType != ExprSafeType) { + S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint) + << EType << is_input_expr << Info.getConstraintStr() + << E->getSourceRange(); + return true; + } + + return false; +} + StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, @@ -124,8 +155,14 @@ 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()); + // If we're compiling CUDA file and function attributes indicate that it's not + // for this compilation side, skip all the checks. + if (!DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) { + GCCAsmStmt *NS = new (Context) GCCAsmStmt( + Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, + Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc); + return NS; + } for (unsigned i = 0; i != NumOutputs; i++) { StringLiteral *Literal = Constraints[i]; @@ -136,8 +173,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, OutputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); - if (ValidateConstraints && - !Context.getTargetInfo().validateOutputConstraint(Info)) + if (!Context.getTargetInfo().validateOutputConstraint(Info)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_output_constraint) << Info.getConstraintStr()); @@ -154,13 +190,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (CheckNakedParmReference(OutputExpr, *this)) return StmtError(); - // Bitfield can't be referenced with a pointer. - if (Info.allowsMemory() && OutputExpr->refersToBitField()) - return StmtError(Diag(OutputExpr->getLocStart(), - diag::err_asm_bitfield_in_memory_constraint) - << 1 - << Info.getConstraintStr() - << OutputExpr->getSourceRange()); + // Check that the output expression is compatible with memory constraint. + if (Info.allowsMemory() && + checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false)) + return StmtError(); OutputConstraintInfos.push_back(Info); @@ -219,9 +252,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, InputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); - if (ValidateConstraints && - !Context.getTargetInfo().validateInputConstraint( - OutputConstraintInfos.data(), NumOutputs, Info)) { + if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos, + Info)) { return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_input_constraint) << Info.getConstraintStr()); @@ -238,13 +270,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (CheckNakedParmReference(InputExpr, *this)) return StmtError(); - // Bitfield can't be referenced with a pointer. - if (Info.allowsMemory() && InputExpr->refersToBitField()) - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_bitfield_in_memory_constraint) - << 0 - << Info.getConstraintStr() - << InputExpr->getSourceRange()); + // Check that the input expression is compatible with memory constraint. + if (Info.allowsMemory() && + checkExprMemoryConstraintCompat(*this, InputExpr, Info, true)) + return StmtError(); // Only allow void types for memory constraints. if (Info.allowsMemory() && !Info.allowsRegister()) { @@ -260,8 +289,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return StmtError( Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected) << Info.getConstraintStr() << InputExpr->getSourceRange()); - if (Result.slt(Info.getImmConstantMin()) || - Result.sgt(Info.getImmConstantMax())) + if (!Info.isValidAsmImmediate(Result)) return StmtError(Diag(InputExpr->getLocStart(), diag::err_invalid_asm_value_for_constraint) << Result.toString(10) << Info.getConstraintStr() @@ -392,6 +420,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, diag::err_asm_unexpected_constraint_alternatives) << NumAlternatives << AltCount); } + SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(), + ~0U); for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; StringRef ConstraintStr = Info.getConstraintStr(); @@ -413,6 +443,19 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, Expr *OutputExpr = Exprs[TiedTo]; Expr *InputExpr = Exprs[InputOpNo]; + // Make sure no more than one input constraint matches each output. + assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range"); + if (InputMatchedToOutput[TiedTo] != ~0U) { + Diag(NS->getInputExpr(i)->getLocStart(), + diag::err_asm_input_duplicate_match) + << TiedTo; + Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(), + diag::note_asm_input_duplicate_first) + << TiedTo; + return StmtError(); + } + InputMatchedToOutput[TiedTo] = i; + if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) continue; @@ -504,6 +547,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return NS; } +static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T, + llvm::InlineAsmIdentifierInfo &Info) { + // Compute the type size (and array length if applicable?). + Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity(); + if (T->isArrayType()) { + const ArrayType *ATy = Context.getAsArrayType(T); + Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); + Info.Length = Info.Size / Info.Type; + } +} + ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, @@ -551,13 +605,7 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, return ExprError(); } - // Compute the type size (and array length if applicable?). - Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity(); - if (T->isArrayType()) { - const ArrayType *ATy = Context.getAsArrayType(T); - Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); - Info.Length = Info.Size / Info.Type; - } + fillInlineAsmTypeInfo(Context, T, Info); // We can work with the expression as long as it's not an r-value. if (!Result.get()->isRValue()) @@ -569,47 +617,103 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc) { Offset = 0; + SmallVector<StringRef, 2> Members; + Member.split(Members, "."); + LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(), LookupOrdinaryName); if (!LookupName(BaseResult, getCurScope())) return true; - if (!BaseResult.isSingleResult()) - return true; + LookupResult CurrBaseResult(BaseResult); - const RecordType *RT = nullptr; - NamedDecl *FoundDecl = BaseResult.getFoundDecl(); - if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) - RT = VD->getType()->getAs<RecordType>(); - else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) { - MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); - RT = TD->getUnderlyingType()->getAs<RecordType>(); - } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl)) - RT = TD->getTypeForDecl()->getAs<RecordType>(); - if (!RT) - return true; + for (StringRef NextMember : Members) { - if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0)) - return true; + if (!CurrBaseResult.isSingleResult()) + return true; + + const RecordType *RT = nullptr; + NamedDecl *FoundDecl = CurrBaseResult.getFoundDecl(); + if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) + RT = VD->getType()->getAs<RecordType>(); + else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) { + MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); + RT = TD->getUnderlyingType()->getAs<RecordType>(); + } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl)) + RT = TD->getTypeForDecl()->getAs<RecordType>(); + else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl)) + RT = TD->getType()->getAs<RecordType>(); + if (!RT) + return true; + + if (RequireCompleteType(AsmLoc, QualType(RT, 0), + diag::err_asm_incomplete_type)) + return true; + + LookupResult FieldResult(*this, &Context.Idents.get(NextMember), + SourceLocation(), LookupMemberName); + + if (!LookupQualifiedName(FieldResult, RT->getDecl())) + return true; + + // FIXME: Handle IndirectFieldDecl? + FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); + if (!FD) + return true; + + CurrBaseResult = FieldResult; + + const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl()); + unsigned i = FD->getFieldIndex(); + CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i)); + Offset += (unsigned)Result.getQuantity(); + } + + return false; +} - LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(), +ExprResult +Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, unsigned &Offset, + llvm::InlineAsmIdentifierInfo &Info, + SourceLocation AsmLoc) { + Info.clear(); + + const RecordType *RT = E->getType()->getAs<RecordType>(); + // FIXME: Diagnose this as field access into a scalar type. + if (!RT) + return ExprResult(); + + LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc, LookupMemberName); if (!LookupQualifiedName(FieldResult, RT->getDecl())) - return true; + return ExprResult(); - // FIXME: Handle IndirectFieldDecl? - FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); + // Only normal and indirect field results will work. + ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); if (!FD) - return true; + FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl()); + if (!FD) + return ExprResult(); - const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl()); - unsigned i = FD->getFieldIndex(); - CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i)); - Offset = (unsigned)Result.getQuantity(); + Offset = (unsigned)Context.toCharUnitsFromBits(Context.getFieldOffset(FD)) + .getQuantity(); - return false; + // Make an Expr to thread through OpDecl. + ExprResult Result = BuildMemberReferenceExpr( + E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(), + SourceLocation(), nullptr, FieldResult, nullptr, nullptr); + if (Result.isInvalid()) + return Result; + Info.OpDecl = Result.get(); + + fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info); + + // Fields are "variables" as far as inline assembly is concerned. + Info.IsVarDecl = true; + + return Result; } StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, @@ -646,7 +750,15 @@ LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName, // Create an internal name for the label. The name should not be a valid mangled // name, and should be unique. We use a dot to make the name an invalid mangled // name. - OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__" << ExternalLabelName; + OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__"; + for (auto it = ExternalLabelName.begin(); it != ExternalLabelName.end(); + ++it) { + OS << *it; + if (*it == '$') { + // We escape '$' in asm strings by replacing it with "$$" + OS << '$'; + } + } Label->setMSAsmLabel(OS.str()); } if (AlwaysCreate) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp index 5b71c11..984bd07 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp @@ -65,19 +65,32 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, return nullptr; } - LoopHintAttr::OptionType Option; LoopHintAttr::Spelling Spelling; - if (PragmaUnroll) { - Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll; - Spelling = LoopHintAttr::Pragma_unroll; - } else if (PragmaNoUnroll) { - Option = LoopHintAttr::Unroll; + LoopHintAttr::OptionType Option; + LoopHintAttr::LoopHintState State; + if (PragmaNoUnroll) { + // #pragma nounroll Spelling = LoopHintAttr::Pragma_nounroll; + Option = LoopHintAttr::Unroll; + State = LoopHintAttr::Disable; + } else if (PragmaUnroll) { + Spelling = LoopHintAttr::Pragma_unroll; + if (ValueExpr) { + // #pragma unroll N + Option = LoopHintAttr::UnrollCount; + State = LoopHintAttr::Numeric; + } else { + // #pragma unroll + Option = LoopHintAttr::Unroll; + State = LoopHintAttr::Enable; + } } else { + // #pragma clang loop ... + Spelling = LoopHintAttr::Pragma_clang_loop; assert(OptionLoc && OptionLoc->Ident && "Attribute must have valid option info."); - IdentifierInfo *OptionInfo = OptionLoc->Ident; - Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName()) + Option = llvm::StringSwitch<LoopHintAttr::OptionType>( + OptionLoc->Ident->getName()) .Case("vectorize", LoopHintAttr::Vectorize) .Case("vectorize_width", LoopHintAttr::VectorizeWidth) .Case("interleave", LoopHintAttr::Interleave) @@ -85,31 +98,29 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, .Case("unroll", LoopHintAttr::Unroll) .Case("unroll_count", LoopHintAttr::UnrollCount) .Default(LoopHintAttr::Vectorize); - Spelling = LoopHintAttr::Pragma_clang_loop; - } - - LoopHintAttr::LoopHintState State = LoopHintAttr::Default; - if (PragmaNoUnroll) { - State = LoopHintAttr::Disable; - } else if (Option == LoopHintAttr::VectorizeWidth || - Option == LoopHintAttr::InterleaveCount || - Option == LoopHintAttr::UnrollCount) { - assert(ValueExpr && "Attribute must have a valid value expression."); - if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart())) - return nullptr; - } else if (Option == LoopHintAttr::Vectorize || - Option == LoopHintAttr::Interleave || - Option == LoopHintAttr::Unroll) { - // Default state is assumed if StateLoc is not specified, such as with - // '#pragma unroll'. - if (StateLoc && StateLoc->Ident) { + if (Option == LoopHintAttr::VectorizeWidth || + Option == LoopHintAttr::InterleaveCount || + Option == LoopHintAttr::UnrollCount) { + assert(ValueExpr && "Attribute must have a valid value expression."); + if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart())) + return nullptr; + State = LoopHintAttr::Numeric; + } else if (Option == LoopHintAttr::Vectorize || + Option == LoopHintAttr::Interleave || + Option == LoopHintAttr::Unroll) { + assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument"); if (StateLoc->Ident->isStr("disable")) State = LoopHintAttr::Disable; else if (StateLoc->Ident->isStr("assume_safety")) State = LoopHintAttr::AssumeSafety; - else + else if (StateLoc->Ident->isStr("full")) + State = LoopHintAttr::Full; + else if (StateLoc->Ident->isStr("enable")) State = LoopHintAttr::Enable; - } + else + llvm_unreachable("bad loop hint argument"); + } else + llvm_unreachable("bad loop hint"); } return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State, @@ -139,9 +150,8 @@ CheckForIncompatibleAttributes(Sema &S, if (!LH) continue; - int Option = LH->getOption(); - int Category; - enum { Vectorize, Interleave, Unroll }; + LoopHintAttr::OptionType Option = LH->getOption(); + enum { Vectorize, Interleave, Unroll } Category; switch (Option) { case LoopHintAttr::Vectorize: case LoopHintAttr::VectorizeWidth: @@ -183,7 +193,8 @@ CheckForIncompatibleAttributes(Sema &S, CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) { // Disable hints are not compatible with numeric hints of the same // category. As a special case, numeric unroll hints are also not - // compatible with "enable" form of the unroll pragma, unroll(full). + // compatible with enable or full form of the unroll pragma because these + // directives indicate full unrolling. S.Diag(OptionLoc, diag::err_pragma_loop_compatibility) << /*Duplicate=*/false << CategoryState.StateAttr->getDiagnosticName(Policy) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index 035c37c..6cc8588 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -18,6 +18,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeVisitor.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" @@ -208,7 +209,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S, R.suppressDiagnostics(); } else { assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) || - isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD)); + isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) || + isa<BuiltinTemplateDecl>(TD)); TemplateKind = isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template; } @@ -327,8 +329,8 @@ void Sema::LookupTemplateName(LookupResult &Found, Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) { Found.setLookupName(Corrected.getCorrection()); - if (Corrected.getCorrectionDecl()) - Found.addDecl(Corrected.getCorrectionDecl()); + if (auto *ND = Corrected.getFoundDecl()) + Found.addDecl(ND); FilterAcceptableTemplateNames(Found); if (!Found.empty()) { if (LookupCtx) { @@ -812,14 +814,15 @@ Sema::ActOnTemplateParameterList(unsigned Depth, SourceLocation ExportLoc, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - Decl **Params, unsigned NumParams, + ArrayRef<Decl *> Params, SourceLocation RAngleLoc) { if (ExportLoc.isValid()) Diag(ExportLoc, diag::warn_template_export_unsupported); - return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, - (NamedDecl**)Params, NumParams, - RAngleLoc); + return TemplateParameterList::Create( + Context, TemplateLoc, LAngleLoc, + llvm::makeArrayRef((NamedDecl *const *)Params.data(), Params.size()), + RAngleLoc); } static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { @@ -1089,9 +1092,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, /*DelayTypeCreation=*/true); SetNestedNameSpecifier(NewClass, SS); if (NumOuterTemplateParamLists > 0) - NewClass->setTemplateParameterListsInfo(Context, - NumOuterTemplateParamLists, - OuterTemplateParamLists); + NewClass->setTemplateParameterListsInfo( + Context, llvm::makeArrayRef(OuterTemplateParamLists, + NumOuterTemplateParamLists)); // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. @@ -1936,7 +1939,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( // Fabricate an empty template parameter list for the invented header. return TemplateParameterList::Create(Context, SourceLocation(), - SourceLocation(), nullptr, 0, + SourceLocation(), None, SourceLocation()); } @@ -2017,6 +2020,58 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) { } } +static QualType +checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, + const SmallVectorImpl<TemplateArgument> &Converted, + SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs) { + ASTContext &Context = SemaRef.getASTContext(); + switch (BTD->getBuiltinTemplateKind()) { + case BTK__make_integer_seq: + // Specializations of __make_integer_seq<S, T, N> are treated like + // S<T, 0, ..., N-1>. + + // C++14 [inteseq.intseq]p1: + // T shall be an integer type. + if (!Converted[1].getAsType()->isIntegralType(Context)) { + SemaRef.Diag(TemplateArgs[1].getLocation(), + diag::err_integer_sequence_integral_element_type); + return QualType(); + } + + // C++14 [inteseq.make]p1: + // If N is negative the program is ill-formed. + TemplateArgument NumArgsArg = Converted[2]; + llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); + if (NumArgs < 0) { + SemaRef.Diag(TemplateArgs[2].getLocation(), + diag::err_integer_sequence_negative_length); + return QualType(); + } + + QualType ArgTy = NumArgsArg.getIntegralType(); + TemplateArgumentListInfo SyntheticTemplateArgs; + // The type argument gets reused as the first template argument in the + // synthetic template argument list. + SyntheticTemplateArgs.addArgument(TemplateArgs[1]); + // Expand N into 0 ... N-1. + for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned()); + I < NumArgs; ++I) { + TemplateArgument TA(Context, I, ArgTy); + Expr *E = SemaRef.BuildExpressionFromIntegralTemplateArgument( + TA, TemplateArgs[2].getLocation()) + .getAs<Expr>(); + SyntheticTemplateArgs.addArgument( + TemplateArgumentLoc(TemplateArgument(E), E)); + } + // The first template argument will be reused as the template decl that + // our synthetic template arguments will be applied to. + return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(), + TemplateLoc, SyntheticTemplateArgs); + } + llvm_unreachable("unexpected BuiltinTemplateDecl!"); +} + QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { @@ -2171,6 +2226,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, CanonType = Context.getTypeDeclType(Decl); assert(isa<RecordType>(CanonType) && "type of non-dependent specialization is not a RecordType"); + } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) { + CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc, + TemplateArgs); } // Build the fully-sugared type for this class template @@ -2469,25 +2527,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization( false, Converted)) return true; - // Check that the type of this variable template specialization - // matches the expected type. - TypeSourceInfo *ExpectedDI; - { - // Do substitution on the type of the declaration - TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack, - Converted.data(), Converted.size()); - InstantiatingTemplate Inst(*this, TemplateKWLoc, VarTemplate); - if (Inst.isInvalid()) - return true; - VarDecl *Templated = VarTemplate->getTemplatedDecl(); - ExpectedDI = - SubstType(Templated->getTypeSourceInfo(), - MultiLevelTemplateArgumentList(TemplateArgList), - Templated->getTypeSpecStartLoc(), Templated->getDeclName()); - } - if (!ExpectedDI) - return true; - // Find the variable template (partial) specialization declaration that // corresponds to these arguments. if (IsPartialSpecialization) { @@ -2710,7 +2749,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, typedef PartialSpecMatchResult MatchResult; SmallVector<MatchResult, 4> Matched; SourceLocation PointOfInstantiation = TemplateNameLoc; - TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation); + TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation, + /*ForTakingAddress=*/false); // 1. Attempt to find the closest partial specialization that this // specializes, if any. @@ -3242,7 +3282,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef, TemplateArgLists.addOuterTemplateArguments(None); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext ConstantEvaluated(SemaRef, + Sema::ConstantEvaluated); return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists); } @@ -3733,9 +3774,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // We're done with this parameter pack. Pack up its arguments and add // them to the list. Converted.push_back( - TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); + TemplateArgument::CreatePackCopy(Context, ArgumentPack)); ArgumentPack.clear(); // This argument is assigned to the next parameter. @@ -3816,10 +3855,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // If we're checking a partial template argument list, we're done. if (PartialTemplateArgs) { if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty()) - Converted.push_back(TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); - + Converted.push_back( + TemplateArgument::CreatePackCopy(Context, ArgumentPack)); + return false; } @@ -3835,9 +3873,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (Param + 1 != ParamEnd) return true; - Converted.push_back(TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); + Converted.push_back( + TemplateArgument::CreatePackCopy(Context, ArgumentPack)); ArgumentPack.clear(); ++Param; @@ -3946,7 +3983,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // No problems found with the new argument list, propagate changes back // to caller. - TemplateArgs = NewArgs; + TemplateArgs = std::move(NewArgs); return false; } @@ -4245,7 +4282,11 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *Arg) { if (Arg->isValueDependent() || Arg->isTypeDependent()) return NPV_NotNullPointer; - + + if (!S.isCompleteType(Arg->getExprLoc(), ParamType)) + llvm_unreachable( + "Incomplete parameter type in isNullPointerValueTemplateArgument!"); + if (!S.getLangOpts().CPlusPlus11) return NPV_NotNullPointer; @@ -4693,8 +4734,6 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null); Converted = TemplateArgument(S.Context.getCanonicalType(ParamType), /*isNullPtr*/true); - if (S.Context.getTargetInfo().getCXXABI().isMicrosoft()) - S.RequireCompleteType(Arg->getExprLoc(), ParamType, 0); return false; case NPV_NotNullPointer: break; @@ -6311,9 +6350,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, PrevPartial); SetNestedNameSpecifier(Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { - Partial->setTemplateParameterListsInfo(Context, - TemplateParameterLists.size() - 1, - TemplateParameterLists.data()); + Partial->setTemplateParameterListsInfo( + Context, TemplateParameterLists.drop_back(1)); } if (!PrevPartial) @@ -6367,14 +6405,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, SetNestedNameSpecifier(Specialization, SS); if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, - TemplateParameterLists.size(), - TemplateParameterLists.data()); + TemplateParameterLists); } if (!PrevDecl) ClassTemplate->AddSpecialization(Specialization, InsertPos); - CanonType = Context.getTypeDeclType(Specialization); + if (CurContext->isDependentContext()) { + // -fms-extensions permits specialization of nested classes without + // fully specializing the outer class(es). + assert(getLangOpts().MicrosoftExt && + "Only possible with -fms-extensions!"); + TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); + CanonType = Context.getTemplateSpecializationType( + CanonTemplate, Converted.data(), Converted.size()); + } else { + CanonType = Context.getTypeDeclType(Specialization); + } } // C++ [temp.expl.spec]p6: @@ -6497,24 +6544,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S, return NewDecl; } -Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, - MultiTemplateParamsArg TemplateParameterLists, - Declarator &D) { - assert(getCurFunctionDecl() == nullptr && "Function parsing confused"); - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - - if (FTI.hasPrototype) { - // FIXME: Diagnose arguments without names in C. - } - - Scope *ParentScope = FnBodyScope->getParent(); - - D.setFunctionDefinitionKind(FDK_Definition); - Decl *DP = HandleDeclarator(ParentScope, D, - TemplateParameterLists); - return ActOnStartOfFunctionDef(FnBodyScope, DP); -} - /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { @@ -6795,7 +6824,11 @@ bool Sema::CheckFunctionTemplateSpecialization( // The set of function template specializations that could match this // explicit function template specialization. UnresolvedSet<8> Candidates; - TemplateSpecCandidateSet FailedCandidates(FD->getLocation()); + TemplateSpecCandidateSet FailedCandidates(FD->getLocation(), + /*ForTakingAddress=*/false); + + llvm::SmallDenseMap<FunctionDecl *, TemplateArgumentListInfo, 8> + ConvertedTemplateArgs; DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); @@ -6826,6 +6859,10 @@ bool Sema::CheckFunctionTemplateSpecialization( } } + TemplateArgumentListInfo Args; + if (ExplicitTemplateArgs) + Args = *ExplicitTemplateArgs; + // C++ [temp.expl.spec]p11: // A trailing template-argument can be left unspecified in the // template-id naming an explicit function template specialization @@ -6837,7 +6874,7 @@ bool Sema::CheckFunctionTemplateSpecialization( FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult TDK = DeduceTemplateArguments( cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()), - ExplicitTemplateArgs, FT, Specialization, Info)) { + ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info)) { // Template argument deduction failed; record why it failed, so // that we can provide nifty diagnostics. FailedCandidates.addCandidate() @@ -6848,6 +6885,8 @@ bool Sema::CheckFunctionTemplateSpecialization( } // Record this candidate. + if (ExplicitTemplateArgs) + ConvertedTemplateArgs[Specialization] = std::move(Args); Candidates.addDecl(Specialization, I.getAccess()); } } @@ -6926,10 +6965,10 @@ bool Sema::CheckFunctionTemplateSpecialization( // Take copies of (semantic and syntactic) template argument lists. const TemplateArgumentList* TemplArgs = new (Context) TemplateArgumentList(Specialization->getTemplateSpecializationArgs()); - FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(), - TemplArgs, /*InsertPos=*/nullptr, - SpecInfo->getTemplateSpecializationKind(), - ExplicitTemplateArgs); + FD->setFunctionTemplateSpecialization( + Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr, + SpecInfo->getTemplateSpecializationKind(), + ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr); // The "previous declaration" for this function template specialization is // the prior function template specialization. @@ -7429,11 +7468,16 @@ Sema::ActOnExplicitInstantiation(Scope *S, } } + // Set the template specialization kind. Make sure it is set before + // instantiating the members which will trigger ASTConsumer callbacks. + Specialization->setTemplateSpecializationKind(TSK); InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); + } else { + + // Set the template specialization kind. + Specialization->setTemplateSpecializationKind(TSK); } - // Set the template specialization kind. - Specialization->setTemplateSpecializationKind(TSK); return Specialization; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index ae8157e..de04c8a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -679,7 +679,7 @@ public: new (S.Context) TemplateArgument[Pack.New.size()]; std::copy(Pack.New.begin(), Pack.New.end(), ArgumentPack); NewPack = DeducedTemplateArgument( - TemplateArgument(ArgumentPack, Pack.New.size()), + TemplateArgument(llvm::makeArrayRef(ArgumentPack, Pack.New.size())), Pack.New[0].wasDeducedFromArrayBound()); } @@ -1440,7 +1440,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, // We cannot inspect base classes as part of deduction when the type // is incomplete, so either instantiate any templates necessary to // complete the type, or skip over it if it cannot be completed. - if (S.RequireCompleteType(Info.getLocation(), Arg, 0)) + if (!S.isCompleteType(Info.getLocation(), Arg)) return Result; // Use data recursion to crawl through the list of base classes. @@ -1517,10 +1517,19 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, if (!MemPtrArg) return Sema::TDK_NonDeducedMismatch; + QualType ParamPointeeType = MemPtrParam->getPointeeType(); + if (ParamPointeeType->isFunctionType()) + S.adjustMemberFunctionCC(ParamPointeeType, /*IsStatic=*/true, + /*IsCtorOrDtor=*/false, Info.getLocation()); + QualType ArgPointeeType = MemPtrArg->getPointeeType(); + if (ArgPointeeType->isFunctionType()) + S.adjustMemberFunctionCC(ArgPointeeType, /*IsStatic=*/true, + /*IsCtorOrDtor=*/false, Info.getLocation()); + if (Sema::TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, - MemPtrParam->getPointeeType(), - MemPtrArg->getPointeeType(), + ParamPointeeType, + ArgPointeeType, Info, Deduced, TDF & TDF_IgnoreQualifiers)) return Result; @@ -2075,9 +2084,8 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, } // Create the resulting argument pack. - Output.push_back(TemplateArgument::CreatePackCopy(S.Context, - PackedArgsBuilder.data(), - PackedArgsBuilder.size())); + Output.push_back( + TemplateArgument::CreatePackCopy(S.Context, PackedArgsBuilder)); return false; } @@ -2730,7 +2738,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg, return false; if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) && - S.IsDerivedFrom(A, DeducedA)) + S.IsDerivedFrom(SourceLocation(), A, DeducedA)) return false; return true; @@ -2850,7 +2858,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs, &NumExplicitArgs) == Param) { - Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs)); + Builder.push_back(TemplateArgument( + llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs))); // Forget the partially-substituted pack; it's substitution is now // complete. @@ -3028,7 +3037,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, // Gather the explicit template arguments, if any. TemplateArgumentListInfo ExplicitTemplateArgs; if (Ovl->hasExplicitTemplateArgs()) - Ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); + Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs); QualType Match; for (UnresolvedSetIterator I = Ovl->decls_begin(), E = Ovl->decls_end(); I != E; ++I) { @@ -3123,8 +3132,10 @@ 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)) + if (ArgType->isIncompleteArrayType()) { + S.completeExprArrayBound(Arg); ArgType = Arg->getType(); + } // C++0x [temp.deduct.call]p3: // If P is an rvalue reference to a cv-unqualified template @@ -3203,24 +3214,63 @@ DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF, Sema::TemplateDeductionResult &Result) { - // If the argument is an initializer list then the parameter is an undeduced - // context, unless the parameter type is (reference to cv) - // std::initializer_list<P'>, in which case deduction is done for each element - // of the initializer list as-if it were an argument in a function call, and - // the result is the deduced type if it's the same for all elements. - QualType X; - if (!S.isStdInitializerList(AdjustedParamType, &X)) + + // [temp.deduct.call] p1 (post CWG-1591) + // If removing references and cv-qualifiers from P gives + // std::initializer_list<P0> or P0[N] for some P0 and N and the argument is a + // non-empty initializer list (8.5.4), then deduction is performed instead for + // each element of the initializer list, taking P0 as a function template + // parameter type and the initializer element as its argument, and in the + // P0[N] case, if N is a non-type template parameter, N is deduced from the + // length of the initializer list. Otherwise, an initializer list argument + // causes the parameter to be considered a non-deduced context + + const bool IsConstSizedArray = AdjustedParamType->isConstantArrayType(); + + const bool IsDependentSizedArray = + !IsConstSizedArray && AdjustedParamType->isDependentSizedArrayType(); + + QualType ElTy; // The element type of the std::initializer_list or the array. + + const bool IsSTDList = !IsConstSizedArray && !IsDependentSizedArray && + S.isStdInitializerList(AdjustedParamType, &ElTy); + + if (!IsConstSizedArray && !IsDependentSizedArray && !IsSTDList) return false; Result = Sema::TDK_Success; - - // Recurse down into the init list. - for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) { - if ((Result = DeduceTemplateArgumentByListElement( - S, TemplateParams, X, ILE->getInit(i), Info, Deduced, TDF))) - return true; + // If we are not deducing against the 'T' in a std::initializer_list<T> then + // deduce against the 'T' in T[N]. + if (ElTy.isNull()) { + assert(!IsSTDList); + ElTy = S.Context.getAsArrayType(AdjustedParamType)->getElementType(); + } + // Deduction only needs to be done for dependent types. + if (ElTy->isDependentType()) { + for (Expr *E : ILE->inits()) { + if ((Result = DeduceTemplateArgumentByListElement(S, TemplateParams, ElTy, + E, Info, Deduced, TDF))) + return true; + } } + if (IsDependentSizedArray) { + const DependentSizedArrayType *ArrTy = + S.Context.getAsDependentSizedArrayType(AdjustedParamType); + // Determine the array bound is something we can deduce. + if (NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(ArrTy->getSizeExpr())) { + // We can perform template argument deduction for the given non-type + // template parameter. + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument at depth > 0"); + llvm::APInt Size(S.Context.getIntWidth(NTTP->getType()), + ILE->getNumInits()); + Result = DeduceNonTypeTemplateArgument( + S, NTTP, llvm::APSInt(Size), NTTP->getType(), + /*ArrayBound=*/true, Info, Deduced); + } + } return true; } @@ -3908,7 +3958,7 @@ namespace { !Replacement.isNull() && Replacement->isDependentType(); QualType Result = SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement, - TL.getTypePtr()->isDecltypeAuto(), + TL.getTypePtr()->getKeyword(), Dependent); AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result); NewTL.setNameLoc(TL.getNameLoc()); @@ -3976,6 +4026,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) { if (Result.isNull()) return DAR_FailedAlreadyDiagnosed; return DAR_Succeeded; + } else if (!getLangOpts().CPlusPlus) { + if (isa<InitListExpr>(Init)) { + Diag(Init->getLocStart(), diag::err_auto_init_list_from_c); + return DAR_FailedAlreadyDiagnosed; + } } } @@ -3989,8 +4044,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) { nullptr, false, false); QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0); NamedDecl *TemplParamPtr = TemplParam; - FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr, - Loc); + FixedSizeTemplateParameterListStorage<1> TemplateParamsSt( + Loc, Loc, TemplParamPtr, Loc); QualType FuncParam = SubstituteAutoTransform(*this, TemplArg).Apply(Type); assert(!FuncParam.isNull() && @@ -4007,20 +4062,24 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) { InitListExpr *InitList = dyn_cast<InitListExpr>(Init); if (InitList) { for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) { - if (DeduceTemplateArgumentByListElement(*this, &TemplateParams, - TemplArg, - InitList->getInit(i), + if (DeduceTemplateArgumentByListElement(*this, TemplateParamsSt.get(), + TemplArg, InitList->getInit(i), Info, Deduced, TDF)) return DAR_Failed; } } else { - if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams, - FuncParam, InitType, Init, - TDF)) + if (!getLangOpts().CPlusPlus && Init->refersToBitField()) { + Diag(Loc, diag::err_auto_bitfield); + return DAR_FailedAlreadyDiagnosed; + } + + if (AdjustFunctionParmAndArgTypesForDeduction( + *this, TemplateParamsSt.get(), FuncParam, InitType, Init, TDF)) return DAR_Failed; - if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam, - InitType, Info, Deduced, TDF)) + if (DeduceTemplateArgumentsByTypeMatch(*this, TemplateParamsSt.get(), + FuncParam, InitType, Info, Deduced, + TDF)) return DAR_Failed; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index c1961e5..fb7fc10 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -817,14 +817,6 @@ namespace { QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB, SubstTemplateTypeParmPackTypeLoc TL); - ExprResult TransformCallExpr(CallExpr *CE) { - getSema().CallsUndergoingInstantiation.push_back(CE); - ExprResult Result = - TreeTransform<TemplateInstantiator>::TransformCallExpr(CE); - getSema().CallsUndergoingInstantiation.pop_back(); - return Result; - } - ExprResult TransformLambdaExpr(LambdaExpr *E) { LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); return TreeTransform<TemplateInstantiator>::TransformLambdaExpr(E); @@ -1231,7 +1223,7 @@ TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) { // Transform each of the parameter expansions into the corresponding // parameters in the instantiation of the function decl. - SmallVector<Decl *, 8> Parms; + SmallVector<ParmVarDecl *, 8> Parms; Parms.reserve(E->getNumExpansions()); for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end(); I != End; ++I) { @@ -1682,15 +1674,17 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm); } else if (Expr *Arg = OldParm->getDefaultArg()) { FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext()); - CXXRecordDecl *ClassD = dyn_cast<CXXRecordDecl>(OwningFunc->getDeclContext()); - if (ClassD && ClassD->isLocalClass() && !ClassD->isLambda()) { - // If this is a method of a local class, as per DR1484 its default - // arguments must be instantiated. - Sema::ContextRAII SavedContext(*this, ClassD); + if (OwningFunc->isLexicallyWithinFunctionOrMethod()) { + // Instantiate default arguments for methods of local classes (DR1484) + // and non-defining declarations. + Sema::ContextRAII SavedContext(*this, OwningFunc); LocalInstantiationScope Local(*this); ExprResult NewArg = SubstExpr(Arg, TemplateArgs); - if (NewArg.isUsable()) - NewParm->setDefaultArg(NewArg.get()); + if (NewArg.isUsable()) { + // It would be nice if we still had this. + SourceLocation EqualLoc = NewArg.get()->getLocStart(); + SetParamDefaultArgument(NewParm, NewArg.get(), EqualLoc); + } } else { // FIXME: if we non-lazily instantiated non-dependent default args for // non-dependent parameter types we could remove a bunch of duplicate @@ -1843,9 +1837,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, Invalid = true; } - if (!Invalid && - AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(), - InstantiatedBases.size())) + if (!Invalid && AttachBaseSpecifiers(Instantiation, InstantiatedBases)) Invalid = true; return Invalid; @@ -2050,7 +2042,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, // Default arguments are parsed, if not instantiated. We can go instantiate // default arg exprs for default constructors if necessary now. - ActOnFinishCXXMemberDefaultArgs(Instantiation); + ActOnFinishCXXNonNestedClass(Instantiation); // Instantiate late parsed attributes, and attach them to their decls. // See Sema::InstantiateAttrs @@ -2672,16 +2664,17 @@ ExprResult Sema::SubstInitializer(Expr *Init, return Instantiator.TransformInitializer(Init, CXXDirectInit); } -bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall, +bool Sema::SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall, const MultiLevelTemplateArgumentList &TemplateArgs, SmallVectorImpl<Expr *> &Outputs) { - if (NumExprs == 0) + if (Exprs.empty()) return false; TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), DeclarationName()); - return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs); + return Instantiator.TransformExprs(Exprs.data(), Exprs.size(), + IsCall, Outputs); } NestedNameSpecifierLoc @@ -2806,14 +2799,14 @@ void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) { #endif Stored = Inst; } else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) { - Pack->push_back(Inst); + Pack->push_back(cast<ParmVarDecl>(Inst)); } else { assert(Stored.get<Decl *>() == Inst && "Already instantiated this local"); } } -void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D, - Decl *Inst) { +void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D, + ParmVarDecl *Inst) { D = getCanonicalParmVarDecl(D); DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>(); Pack->push_back(Inst); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index aff2d1c..7a452af 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -813,6 +813,14 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { Enum->setAccess(D->getAccess()); // Forward the mangling number from the template to the instantiated decl. SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D)); + // See if the old tag was defined along with a declarator. + // If it did, mark the new tag as being associated with that declarator. + if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D)) + SemaRef.Context.addDeclaratorForUnnamedTagDecl(Enum, DD); + // See if the old tag was defined along with a typedef. + // If it did, mark the new tag as being associated with that typedef. + if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D)) + SemaRef.Context.addTypedefNameForUnnamedTagDecl(Enum, TND); if (SubstQualifier(D, Enum)) return nullptr; Owner->addDecl(Enum); @@ -827,7 +835,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { SemaRef.SubstType(TI->getType(), TemplateArgs, UnderlyingLoc, DeclarationName()); SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), - DefnUnderlying, Enum); + DefnUnderlying, + /*EnumUnderlyingIsImplicit=*/false, Enum); } } @@ -913,6 +922,11 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { llvm_unreachable("EnumConstantDecls can only occur within EnumDecls."); } +Decl * +TemplateDeclInstantiator::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { + llvm_unreachable("BuiltinTemplateDecls cannot be instantiated."); +} + Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None); @@ -1143,6 +1157,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) { VarDecl *VarInst = cast_or_null<VarDecl>(VisitVarDecl(Pattern, /*InstantiatingVarTemplate=*/true)); + if (!VarInst) return nullptr; DeclContext *DC = Owner; @@ -1297,6 +1312,16 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { SemaRef.Context.setManglingNumber(Record, SemaRef.Context.getManglingNumber(D)); + // See if the old tag was defined along with a declarator. + // If it did, mark the new tag as being associated with that declarator. + if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D)) + SemaRef.Context.addDeclaratorForUnnamedTagDecl(Record, DD); + + // See if the old tag was defined along with a typedef. + // If it did, mark the new tag as being associated with that typedef. + if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D)) + SemaRef.Context.addTypedefNameForUnnamedTagDecl(Record, TND); + Owner->addDecl(Record); // DR1484 clarifies that the members of a local class are instantiated as part @@ -1657,7 +1682,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, SmallVector<TemplateParameterList *, 4> TempParamLists; unsigned NumTempParamLists = 0; if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) { - TempParamLists.set_size(NumTempParamLists); + TempParamLists.resize(NumTempParamLists); for (unsigned I = 0; I != NumTempParamLists; ++I) { TemplateParameterList *TempParams = D->getTemplateParameterList(I); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); @@ -1809,9 +1834,9 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, // context (which will be a namespace scope) as the template. if (isFriend) { if (NumTempParamLists) - Method->setTemplateParameterListsInfo(SemaRef.Context, - NumTempParamLists, - TempParamLists.data()); + Method->setTemplateParameterListsInfo( + SemaRef.Context, + llvm::makeArrayRef(TempParamLists.data(), NumTempParamLists)); Method->setLexicalDeclContext(Owner); Method->setObjectOfFriendDecl(); @@ -2742,7 +2767,7 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { TemplateParameterList *InstL = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(), - L->getLAngleLoc(), &Params.front(), N, + L->getLAngleLoc(), Params, L->getRAngleLoc()); return InstL; } @@ -3246,16 +3271,11 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, // exception specification. // DR1484: Local classes and their members are instantiated along with the // containing function. - bool RequireInstantiation = false; - if (CXXRecordDecl *Cls = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext())) { - if (Cls->isLocalClass()) - RequireInstantiation = true; - } if (SemaRef.getLangOpts().CPlusPlus11 && EPI.ExceptionSpec.Type != EST_None && EPI.ExceptionSpec.Type != EST_DynamicNone && EPI.ExceptionSpec.Type != EST_BasicNoexcept && - !RequireInstantiation) { + !Tmpl->isLexicallyWithinFunctionOrMethod()) { FunctionDecl *ExceptionSpecTemplate = Tmpl; if (EPI.ExceptionSpec.Type == EST_Uninstantiated) ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate; @@ -3619,19 +3639,6 @@ void Sema::BuildVariableInstantiation( NewVar->setReferenced(OldVar->isReferenced()); } - // See if the old variable had a type-specifier that defined an anonymous tag. - // If it did, mark the new variable as being the declarator for the new - // anonymous tag. - if (const TagType *OldTagType = OldVar->getType()->getAs<TagType>()) { - TagDecl *OldTag = OldTagType->getDecl(); - if (OldTag->getDeclaratorForAnonDecl() == OldVar) { - TagDecl *NewTag = NewVar->getType()->castAs<TagType>()->getDecl(); - assert(!NewTag->hasNameForLinkage() && - !NewTag->hasDeclaratorForAnonDecl()); - NewTag->setDeclaratorForAnonDecl(NewVar); - } - } - InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope); LookupResult Previous( diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp index fd3ba35..61052f0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -737,6 +737,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_interface: case TST_class: case TST_auto: + case TST_auto_type: case TST_decltype_auto: case TST_unknown_anytype: case TST_error: @@ -867,8 +868,8 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, MarkAnyDeclReferenced(OpLoc, ParameterPack, true); - return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, - ParameterPack, NameLoc, RParenLoc); + return SizeOfPackExpr::Create(Context, OpLoc, ParameterPack, NameLoc, + RParenLoc); } TemplateArgumentLoc diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index 02a31ef..c70568c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -26,7 +26,6 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" @@ -211,10 +210,8 @@ namespace { /// Diagnose all the ignored type attributes, given that the /// declarator worked out to the given type. void diagnoseIgnoredTypeAttrs(QualType type) const { - for (SmallVectorImpl<AttributeList*>::const_iterator - i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end(); - i != e; ++i) - diagnoseBadTypeAttribute(getSema(), **i, type); + for (auto *Attr : ignoredTypeAttrs) + diagnoseBadTypeAttribute(getSema(), *Attr, type); } ~TypeProcessingState() { @@ -702,7 +699,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, - /*ESpecLoc=*/NoLoc, + /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, @@ -792,18 +789,33 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, TypeSourceInfo *typeArgInfo = typeArgs[i]; QualType typeArg = typeArgInfo->getType(); - // Type arguments cannot explicitly specify nullability. - if (auto nullability = AttributedType::stripOuterNullability(typeArg)) { - SourceLocation nullabilityLoc - = typeArgInfo->getTypeLoc().findNullabilityLoc(); - SourceLocation diagLoc = nullabilityLoc.isValid()? nullabilityLoc - : typeArgInfo->getTypeLoc().getLocStart(); - S.Diag(diagLoc, - diag::err_type_arg_explicit_nullability) - << typeArg - << FixItHint::CreateRemoval(nullabilityLoc); + // Type arguments cannot have explicit qualifiers or nullability. + // We ignore indirect sources of these, e.g. behind typedefs or + // template arguments. + if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) { + bool diagnosed = false; + SourceRange rangeToRemove; + if (auto attr = qual.getAs<AttributedTypeLoc>()) { + rangeToRemove = attr.getLocalSourceRange(); + if (attr.getTypePtr()->getImmediateNullability()) { + typeArg = attr.getTypePtr()->getModifiedType(); + S.Diag(attr.getLocStart(), + diag::err_objc_type_arg_explicit_nullability) + << typeArg << FixItHint::CreateRemoval(rangeToRemove); + diagnosed = true; + } + } + + if (!diagnosed) { + S.Diag(qual.getLocStart(), diag::err_objc_type_arg_qualified) + << typeArg << typeArg.getQualifiers().getAsString() + << FixItHint::CreateRemoval(rangeToRemove); + } } + // Remove qualifiers even if they're non-local. + typeArg = typeArg.getUnqualifiedType(); + finalTypeArgs.push_back(typeArg); if (typeArg->getAs<PackExpansionType>()) @@ -1377,11 +1389,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { if (Result.isNull()) { 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 (Result->getAs<AtomicType>()) { + StringRef TypeName = Result.getBaseTypeIdentifier()->getName(); + bool NoExtTypes = + llvm::StringSwitch<bool>(TypeName) + .Cases("atomic_int", "atomic_uint", "atomic_float", + "atomic_flag", true) + .Default(false); if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) { S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) << Result << "cl_khr_int64_base_atomics"; @@ -1393,12 +1407,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { << Result << "cl_khr_int64_extended_atomics"; declarator.setInvalidType(true); } - if (!S.getOpenCLOptions().cl_khr_fp64 && BT && - BT->getKind() == BuiltinType::Double) { + if (!S.getOpenCLOptions().cl_khr_fp64 && + !TypeName.compare("atomic_double")) { S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) << Result << "cl_khr_fp64"; declarator.setInvalidType(true); } + } else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing && + (Result->isImage2dMSAAT() || Result->isImage2dArrayMSAAT() || + Result->isImage2dArrayMSAATDepth() || + Result->isImage2dMSAATDepth())) { + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) + << Result << "cl_khr_gl_msaa_sharing"; + declarator.setInvalidType(true); } } @@ -1482,14 +1503,17 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // template type parameter. Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0); } else { - Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false); + Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false); } break; + case DeclSpec::TST_auto_type: + Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false); + break; + case DeclSpec::TST_decltype_auto: - Result = Context.getAutoType(QualType(), - /*decltype(auto)*/true, - /*IsDependent*/ false); + Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto, + /*IsDependent*/ false); break; case DeclSpec::TST_unknown_anytype: @@ -1540,8 +1564,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // Apply any type attributes from the decl spec. This may cause the // list of type attributes to be temporarily saved while the type // attributes are pushed around. - if (AttributeList *attrs = DS.getAttributes().getList()) - processTypeAttrs(state, Result, TAL_DeclSpec, attrs); + processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList()); // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { @@ -1975,7 +1998,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (Context.getTargetInfo().getCXXABI().isMicrosoft()) if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) if (!MPTy->getClass()->isDependentType()) - RequireCompleteType(Loc, T, 0); + (void)isCompleteType(Loc, T); } else { // C99 6.7.5.2p1: If the element type is an incomplete or function type, @@ -2103,12 +2126,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (T->isVariableArrayType()) { // Prohibit the use of non-POD types in VLAs. QualType BaseT = Context.getBaseElementType(T); - if (!T->isDependentType() && - !RequireCompleteType(Loc, BaseT, 0) && - !BaseT.isPODType(Context) && - !BaseT->isObjCLifetimeType()) { - Diag(Loc, diag::err_vla_non_pod) - << BaseT; + if (!T->isDependentType() && isCompleteType(Loc, BaseT) && + !BaseT.isPODType(Context) && !BaseT->isObjCLifetimeType()) { + Diag(Loc, diag::err_vla_non_pod) << BaseT; return QualType(); } // Prohibit the use of VLAs during template argument deduction. @@ -2122,7 +2142,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, } else if (ASM != ArrayType::Normal || Quals != 0) Diag(Loc, getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx - : diag::ext_c99_array_usage) << ASM; + : diag::ext_c99_array_usage) << ASM; } if (T->isVariableArrayType()) { @@ -2271,8 +2291,11 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, // Adjust the default free function calling convention to the default method // calling convention. + bool IsCtorOrDtor = + (Entity.getNameKind() == DeclarationName::CXXConstructorName) || + (Entity.getNameKind() == DeclarationName::CXXDestructorName); if (T->isFunctionType()) - adjustMemberFunctionCC(T, /*IsStatic=*/false); + adjustMemberFunctionCC(T, /*IsStatic=*/false, IsCtorOrDtor, Loc); return Context.getMemberPointerType(T, Class.getTypePtr()); } @@ -2432,14 +2455,14 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, return; struct Qual { - unsigned Mask; const char *Name; + unsigned Mask; SourceLocation Loc; } const QualKinds[4] = { - { DeclSpec::TQ_const, "const", ConstQualLoc }, - { DeclSpec::TQ_volatile, "volatile", VolatileQualLoc }, - { DeclSpec::TQ_restrict, "restrict", RestrictQualLoc }, - { DeclSpec::TQ_atomic, "_Atomic", AtomicQualLoc } + { "const", DeclSpec::TQ_const, ConstQualLoc }, + { "volatile", DeclSpec::TQ_volatile, VolatileQualLoc }, + { "restrict", DeclSpec::TQ_restrict, RestrictQualLoc }, + { "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc } }; SmallString<32> QualStr; @@ -2455,7 +2478,7 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, // If we have a location for the qualifier, offer a fixit. SourceLocation QualLoc = QualKinds[I].Loc; - if (!QualLoc.isInvalid()) { + if (QualLoc.isValid()) { FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc); if (Loc.isInvalid() || getSourceManager().isBeforeInTranslationUnit(QualLoc, Loc)) @@ -2548,8 +2571,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // The TagDecl owned by the DeclSpec. TagDecl *OwnedTagDecl = nullptr; - bool ContainsPlaceholderType = false; - switch (D.getName().getKind()) { case UnqualifiedId::IK_ImplicitSelfParam: case UnqualifiedId::IK_OperatorFunctionId: @@ -2557,7 +2578,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_TemplateId: T = ConvertDeclSpecToType(state); - ContainsPlaceholderType = D.getDeclSpec().containsPlaceholderType(); if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) { OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); @@ -2572,8 +2592,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // Constructors and destructors don't have return types. Use // "void" instead. T = SemaRef.Context.VoidTy; - if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList()) - processTypeAttrs(state, T, TAL_DeclSpec, attrs); + processTypeAttrs(state, T, TAL_DeclSpec, + D.getDeclSpec().getAttributes().getList()); break; case UnqualifiedId::IK_ConversionFunctionId: @@ -2581,7 +2601,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // converts to. T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId, &ReturnTypeInfo); - ContainsPlaceholderType = T->getContainedAutoType(); break; } @@ -2589,17 +2608,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, distributeTypeAttrsFromDeclarator(state, T); // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. - // In C++11, a function declarator using 'auto' must have a trailing return - // type (this is checked later) and we can skip this. In other languages - // using auto, we need to check regardless. - // C++14 In generic lambdas allow 'auto' in their parameters. - if (ContainsPlaceholderType && - (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) { + if (D.getDeclSpec().containsPlaceholderType()) { int Error = -1; switch (D.getContext()) { - case Declarator::KNRTypeListContext: - llvm_unreachable("K&R type lists aren't allowed in C++"); case Declarator::LambdaExprContext: llvm_unreachable("Can't specify a type specifier in lambda grammar"); case Declarator::ObjCParameterContext: @@ -2608,69 +2620,88 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, Error = 0; break; case Declarator::LambdaExprParameterContext: + // In C++14, generic lambdas allow 'auto' in their parameters. if (!(SemaRef.getLangOpts().CPlusPlus14 && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto)) - Error = 14; + Error = 16; break; - case Declarator::MemberContext: - if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) + case Declarator::MemberContext: { + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static || + D.isFunctionDeclarator()) break; + bool Cxx = SemaRef.getLangOpts().CPlusPlus; switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) { case TTK_Enum: llvm_unreachable("unhandled tag kind"); - case TTK_Struct: Error = 1; /* Struct member */ break; - case TTK_Union: Error = 2; /* Union member */ break; - case TTK_Class: Error = 3; /* Class member */ break; - case TTK_Interface: Error = 4; /* Interface member */ break; + case TTK_Struct: Error = Cxx ? 1 : 2; /* Struct member */ break; + case TTK_Union: Error = Cxx ? 3 : 4; /* Union member */ break; + case TTK_Class: Error = 5; /* Class member */ break; + case TTK_Interface: Error = 6; /* Interface member */ break; } break; + } case Declarator::CXXCatchContext: case Declarator::ObjCCatchContext: - Error = 5; // Exception declaration + Error = 7; // Exception declaration break; case Declarator::TemplateParamContext: - Error = 6; // Template parameter + Error = 8; // Template parameter break; case Declarator::BlockLiteralContext: - Error = 7; // Block literal + Error = 9; // Block literal break; case Declarator::TemplateTypeArgContext: - Error = 8; // Template type argument + Error = 10; // Template type argument break; case Declarator::AliasDeclContext: case Declarator::AliasTemplateContext: - Error = 10; // Type alias + Error = 12; // Type alias break; case Declarator::TrailingReturnContext: - if (!SemaRef.getLangOpts().CPlusPlus14) - Error = 11; // Function return type + if (!SemaRef.getLangOpts().CPlusPlus14 || + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type) + Error = 13; // Function return type break; case Declarator::ConversionIdContext: - if (!SemaRef.getLangOpts().CPlusPlus14) - Error = 12; // conversion-type-id + if (!SemaRef.getLangOpts().CPlusPlus14 || + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type) + Error = 14; // conversion-type-id break; case Declarator::TypeNameContext: - Error = 13; // Generic + Error = 15; // Generic break; case Declarator::FileContext: case Declarator::BlockContext: case Declarator::ForContext: case Declarator::ConditionContext: + break; case Declarator::CXXNewContext: + if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type) + Error = 17; // 'new' type + break; + case Declarator::KNRTypeListContext: + Error = 18; // K&R function parameter break; } if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - Error = 9; - - // In Objective-C it is an error to use 'auto' on a function declarator. - if (D.isFunctionDeclarator()) Error = 11; + // In Objective-C it is an error to use 'auto' on a function declarator + // (and everywhere for '__auto_type'). + if (D.isFunctionDeclarator() && + (!SemaRef.getLangOpts().CPlusPlus11 || + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)) + Error = 13; + + bool HaveTrailing = false; + // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator // contains a trailing return type. That is only legal at the outermost // level. Check all declarator chunks (outermost first) anyway, to give // better diagnostics. - if (SemaRef.getLangOpts().CPlusPlus11 && Error != -1) { + // We don't support '__auto_type' with trailing return types. + if (SemaRef.getLangOpts().CPlusPlus11 && + D.getDeclSpec().getTypeSpecType() != DeclSpec::TST_auto_type) { for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { unsigned chunkIndex = e - i - 1; state.setCurrentChunkIndex(chunkIndex); @@ -2678,6 +2709,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, if (DeclType.Kind == DeclaratorChunk::Function) { const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; if (FTI.hasTrailingReturnType()) { + HaveTrailing = true; Error = -1; break; } @@ -2690,22 +2722,31 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, AutoRange = D.getName().getSourceRange(); if (Error != -1) { - const bool IsDeclTypeAuto = - D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto; + unsigned Keyword; + switch (D.getDeclSpec().getTypeSpecType()) { + case DeclSpec::TST_auto: Keyword = 0; break; + case DeclSpec::TST_decltype_auto: Keyword = 1; break; + case DeclSpec::TST_auto_type: Keyword = 2; break; + default: llvm_unreachable("unknown auto TypeSpecType"); + } SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed) - << IsDeclTypeAuto << Error << AutoRange; + << Keyword << Error << AutoRange; T = SemaRef.Context.IntTy; D.setInvalidType(true); - } else + } else if (!HaveTrailing) { + // If there was a trailing return type, we already got + // warn_cxx98_compat_trailing_return_type in the parser. SemaRef.Diag(AutoRange.getBegin(), diag::warn_cxx98_compat_auto_type_specifier) << AutoRange; + } } if (SemaRef.getLangOpts().CPlusPlus && OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) { // Check the contexts where C++ forbids the declaration of a new class // or enumeration in a type-specifier-seq. + unsigned DiagID = 0; switch (D.getContext()) { case Declarator::TrailingReturnContext: // Class and enumeration definitions are syntactically not allowed in @@ -2725,10 +2766,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::AliasDeclContext: break; case Declarator::AliasTemplateContext: - SemaRef.Diag(OwnedTagDecl->getLocation(), - diag::err_type_defined_in_alias_template) - << SemaRef.Context.getTypeDeclType(OwnedTagDecl); - D.setInvalidType(true); + DiagID = diag::err_type_defined_in_alias_template; break; case Declarator::TypeNameContext: case Declarator::ConversionIdContext: @@ -2737,10 +2775,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::CXXCatchContext: case Declarator::ObjCCatchContext: case Declarator::TemplateTypeArgContext: - SemaRef.Diag(OwnedTagDecl->getLocation(), - diag::err_type_defined_in_type_specifier) - << SemaRef.Context.getTypeDeclType(OwnedTagDecl); - D.setInvalidType(true); + DiagID = diag::err_type_defined_in_type_specifier; break; case Declarator::PrototypeContext: case Declarator::LambdaExprParameterContext: @@ -2749,20 +2784,21 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::KNRTypeListContext: // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. - SemaRef.Diag(OwnedTagDecl->getLocation(), - diag::err_type_defined_in_param_type) - << SemaRef.Context.getTypeDeclType(OwnedTagDecl); - D.setInvalidType(true); + DiagID = diag::err_type_defined_in_param_type; break; case Declarator::ConditionContext: // C++ 6.4p2: // The type-specifier-seq shall not contain typedef and shall not declare // a new class or enumeration. - SemaRef.Diag(OwnedTagDecl->getLocation(), - diag::err_type_defined_in_condition); - D.setInvalidType(true); + DiagID = diag::err_type_defined_in_condition; break; } + + if (DiagID != 0) { + SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID) + << SemaRef.Context.getTypeDeclType(OwnedTagDecl); + D.setInvalidType(true); + } } assert(!T.isNull() && "This function should not return a null type"); @@ -3286,14 +3322,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Are we in an assume-nonnull region? bool inAssumeNonNullRegion = false; - if (S.PP.getPragmaAssumeNonNullLoc().isValid() && - !state.getDeclarator().isObjCWeakProperty() && - !S.deduceWeakPropertyFromType(T)) { + if (S.PP.getPragmaAssumeNonNullLoc().isValid()) { inAssumeNonNullRegion = true; // Determine which file we saw the assume-nonnull region in. FileID file = getNullabilityCompletenessCheckFileID( S, S.PP.getPragmaAssumeNonNullLoc()); - if (!file.isInvalid()) { + if (file.isValid()) { FileNullability &fileNullability = S.NullabilityMap[file]; // If we haven't seen any type nullability before, now we have. @@ -3367,6 +3401,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, complainAboutMissingNullability = CAMN_No; break; } + + // Weak properties are inferred to be nullable. + if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) { + inferNullability = NullabilityKind::Nullable; + break; + } + // fallthrough case Declarator::FileContext: @@ -3699,7 +3740,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, D.setInvalidType(true); } else if (D.getContext() != Declarator::LambdaExprContext && (T.hasQualifiers() || !isa<AutoType>(T) || - cast<AutoType>(T)->isDecltypeAuto())) { + cast<AutoType>(T)->getKeyword() != AutoTypeKeyword::Auto)) { S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_trailing_return_without_auto) << T << D.getDeclSpec().getSourceRange(); @@ -3835,9 +3876,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Exception specs are not allowed in typedefs. Complain, but add it // anyway. if (IsTypedefName && FTI.getExceptionSpecType()) - S.Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef) - << (D.getContext() == Declarator::AliasDeclContext || - D.getContext() == Declarator::AliasTemplateContext); + S.Diag(FTI.getExceptionSpecLocBeg(), + diag::err_exception_spec_in_typedef) + << (D.getContext() == Declarator::AliasDeclContext || + D.getContext() == Declarator::AliasTemplateContext); // If we see "T var();" or "T var(T());" at block scope, it is probably // an attempt to initialize a variable, not a function declaration. @@ -4062,8 +4104,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } // See if there are any attributes on this declarator chunk. - if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs())) - processTypeAttrs(state, T, TAL_DeclChunk, attrs); + processTypeAttrs(state, T, TAL_DeclChunk, + const_cast<AttributeList *>(DeclType.getAttrs())); } assert(!T.isNull() && "T must not be null after this point"); @@ -4156,8 +4198,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } // Apply any undistributed attributes from the declarator. - if (AttributeList *attrs = D.getAttributes()) - processTypeAttrs(state, T, TAL_DeclName, attrs); + processTypeAttrs(state, T, TAL_DeclName, D.getAttributes()); // Diagnose any ignored type attributes. state.diagnoseIgnoredTypeAttrs(T); @@ -4377,7 +4418,7 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) { TypeSourceInfo *ReturnTypeInfo = nullptr; QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo); - if (getLangOpts().ObjCAutoRefCount) { + if (getLangOpts().ObjC1) { Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy); if (ownership != Qualifiers::OCL_None) transferARCOwnership(state, declSpecTy, ownership); @@ -4402,6 +4443,7 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { case AttributedType::attr_objc_gc: return AttributeList::AT_ObjCGC; case AttributedType::attr_objc_ownership: + case AttributedType::attr_objc_inert_unsafe_unretained: return AttributeList::AT_ObjCOwnership; case AttributedType::attr_noreturn: return AttributeList::AT_NoReturn; @@ -5061,11 +5103,6 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, return true; } - // Consume lifetime attributes without further comment outside of - // ARC mode. - if (!S.getLangOpts().ObjCAutoRefCount) - return true; - IdentifierInfo *II = attr.getArgAsIdent(0)->Ident; Qualifiers::ObjCLifetime lifetime; if (II->isStr("none")) @@ -5083,6 +5120,14 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, return true; } + // Just ignore lifetime attributes other than __weak and __unsafe_unretained + // outside of ARC mode. + if (!S.getLangOpts().ObjCAutoRefCount && + lifetime != Qualifiers::OCL_Weak && + lifetime != Qualifiers::OCL_ExplicitNone) { + return true; + } + SplitQualType underlyingType = type.split(); // Check for redundant/conflicting ownership qualifiers. @@ -5123,6 +5168,25 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, << TDS_ObjCObjOrBlock << type; } + // Don't actually add the __unsafe_unretained qualifier in non-ARC files, + // because having both 'T' and '__unsafe_unretained T' exist in the type + // system causes unfortunate widespread consistency problems. (For example, + // they're not considered compatible types, and we mangle them identicially + // as template arguments.) These problems are all individually fixable, + // but it's easier to just not add the qualifier and instead sniff it out + // in specific places using isObjCInertUnsafeUnretainedType(). + // + // Doing this does means we miss some trivial consistency checks that + // would've triggered in ARC, but that's better than trying to solve all + // the coexistence problems with __unsafe_unretained. + if (!S.getLangOpts().ObjCAutoRefCount && + lifetime == Qualifiers::OCL_ExplicitNone) { + type = S.Context.getAttributedType( + AttributedType::attr_objc_inert_unsafe_unretained, + type, type); + return true; + } + QualType origType = type; if (!NonObjCPointer) type = S.Context.getQualifiedType(underlyingType); @@ -5133,19 +5197,29 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, type = S.Context.getAttributedType(AttributedType::attr_objc_ownership, origType, type); - // Forbid __weak if the runtime doesn't support it. - if (lifetime == Qualifiers::OCL_Weak && - !S.getLangOpts().ObjCARCWeak && !NonObjCPointer) { - - // Actually, delay this until we know what we're parsing. + auto diagnoseOrDelay = [](Sema &S, SourceLocation loc, + unsigned diagnostic, QualType type) { if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { S.DelayedDiagnostics.add( sema::DelayedDiagnostic::makeForbiddenType( - S.getSourceManager().getExpansionLoc(AttrLoc), - diag::err_arc_weak_no_runtime, type, /*ignored*/ 0)); + S.getSourceManager().getExpansionLoc(loc), + diagnostic, type, /*ignored*/ 0)); } else { - S.Diag(AttrLoc, diag::err_arc_weak_no_runtime); + S.Diag(loc, diagnostic); } + }; + + // Sometimes, __weak isn't allowed. + if (lifetime == Qualifiers::OCL_Weak && + !S.getLangOpts().ObjCWeak && !NonObjCPointer) { + + // Use a specialized diagnostic if the runtime just doesn't support them. + unsigned diagnostic = + (S.getLangOpts().ObjCWeakRuntime ? diag::err_arc_weak_disabled + : diag::err_arc_weak_no_runtime); + + // In any case, delay the diagnostic until we know what we're parsing. + diagnoseOrDelay(S, AttrLoc, diagnostic, type); attr.setInvalid(); return true; @@ -5158,9 +5232,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, type->getAs<ObjCObjectPointerType>()) { if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) { if (Class->isArcWeakrefUnavailable()) { - S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class); - S.Diag(ObjT->getInterfaceDecl()->getLocation(), - diag::note_class_declared); + S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class); + S.Diag(ObjT->getInterfaceDecl()->getLocation(), + diag::note_class_declared); } } } @@ -5402,9 +5476,12 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, // Pointer type qualifiers can only operate on pointer types, but not // pointer-to-member types. if (!isa<PointerType>(Desugared)) { - S.Diag(Attr.getLoc(), Type->isMemberPointerType() ? - diag::err_attribute_no_member_pointers : - diag::err_attribute_pointers_only) << Attr.getName(); + if (Type->isMemberPointerType()) + S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers) + << Attr.getName(); + else + S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) + << Attr.getName() << 0; return true; } @@ -5843,25 +5920,41 @@ bool Sema::hasExplicitCallingConv(QualType &T) { return false; } -void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) { +void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor, + SourceLocation Loc) { FunctionTypeUnwrapper Unwrapped(*this, T); const FunctionType *FT = Unwrapped.get(); bool IsVariadic = (isa<FunctionProtoType>(FT) && cast<FunctionProtoType>(FT)->isVariadic()); - - // Only adjust types with the default convention. For example, on Windows we - // should adjust a __cdecl type to __thiscall for instance methods, and a - // __thiscall type to __cdecl for static methods. CallingConv CurCC = FT->getCallConv(); - CallingConv FromCC = - Context.getDefaultCallingConvention(IsVariadic, IsStatic); CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic); - if (CurCC != FromCC || FromCC == ToCC) - return; - if (hasExplicitCallingConv(T)) + if (CurCC == ToCC) return; + // MS compiler ignores explicit calling convention attributes on structors. We + // should do the same. + if (Context.getTargetInfo().getCXXABI().isMicrosoft() && IsCtorOrDtor) { + // Issue a warning on ignored calling convention -- except of __stdcall. + // Again, this is what MS compiler does. + if (CurCC != CC_X86StdCall) + Diag(Loc, diag::warn_cconv_structors) + << FunctionType::getNameForCallConv(CurCC); + // Default adjustment. + } else { + // Only adjust types with the default convention. For example, on Windows + // we should adjust a __cdecl type to __thiscall for instance methods, and a + // __thiscall type to __cdecl for static methods. + CallingConv DefaultCC = + Context.getDefaultCallingConvention(IsVariadic, IsStatic); + + if (CurCC != DefaultCC || DefaultCC == ToCC) + return; + + if (hasExplicitCallingConv(T)) + return; + } + FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC)); QualType Wrapped = Unwrapped.wrap(*this, FT); T = Context.getAdjustedType(T, Wrapped); @@ -6077,10 +6170,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // type, but others can be present in the type specifiers even though they // apply to the decl. Here we apply type attributes and ignore the rest. - AttributeList *next; - do { + bool hasOpenCLAddressSpace = false; + while (attrs) { AttributeList &attr = *attrs; - next = attr.getNext(); + attrs = attr.getNext(); // reset to the next here due to early loop continue + // stmts // Skip attributes that were marked to be invalid. if (attr.isInvalid()) @@ -6139,6 +6233,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, case AttributeList::AT_AddressSpace: HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); + hasOpenCLAddressSpace = true; break; OBJC_POINTER_TYPE_ATTRS_CASELIST: if (!handleObjCPointerTypeAttr(state, attr, type)) @@ -6233,7 +6328,83 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, distributeFunctionTypeAttr(state, attr, type); break; } - } while ((attrs = next)); + } + + // If address space is not set, OpenCL 2.0 defines non private default + // address spaces for some cases: + // OpenCL 2.0, section 6.5: + // The address space for a variable at program scope or a static variable + // inside a function can either be __global or __constant, but defaults to + // __global if not specified. + // (...) + // Pointers that are declared without pointing to a named address space point + // to the generic address space. + if (state.getSema().getLangOpts().OpenCLVersion >= 200 && + !hasOpenCLAddressSpace && type.getAddressSpace() == 0 && + (TAL == TAL_DeclSpec || TAL == TAL_DeclChunk)) { + Declarator &D = state.getDeclarator(); + if (state.getCurrentChunkIndex() > 0 && + D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind == + DeclaratorChunk::Pointer) { + type = state.getSema().Context.getAddrSpaceQualType( + type, LangAS::opencl_generic); + } else if (state.getCurrentChunkIndex() == 0 && + D.getContext() == Declarator::FileContext && + !D.isFunctionDeclarator() && !D.isFunctionDefinition() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + !type->isSamplerT()) + type = state.getSema().Context.getAddrSpaceQualType( + type, LangAS::opencl_global); + else if (state.getCurrentChunkIndex() == 0 && + D.getContext() == Declarator::BlockContext && + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) + type = state.getSema().Context.getAddrSpaceQualType( + type, LangAS::opencl_global); + } +} + +void Sema::completeExprArrayBound(Expr *E) { + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) { + if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { + if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) { + SourceLocation PointOfInstantiation = E->getExprLoc(); + + if (MemberSpecializationInfo *MSInfo = + Var->getMemberSpecializationInfo()) { + // If we don't already have a point of instantiation, this is it. + if (MSInfo->getPointOfInstantiation().isInvalid()) { + MSInfo->setPointOfInstantiation(PointOfInstantiation); + + // This is a modification of an existing AST node. Notify + // listeners. + if (ASTMutationListener *L = getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); + } + } else { + VarTemplateSpecializationDecl *VarSpec = + cast<VarTemplateSpecializationDecl>(Var); + if (VarSpec->getPointOfInstantiation().isInvalid()) + VarSpec->setPointOfInstantiation(PointOfInstantiation); + } + + InstantiateVariableDefinition(PointOfInstantiation, Var); + + // Update the type to the newly instantiated definition's type both + // here and within the expression. + if (VarDecl *Def = Var->getDefinition()) { + DRE->setDecl(Def); + QualType T = Def->getType(); + DRE->setType(T); + // FIXME: Update the type on all intervening expressions. + E->setType(T); + } + + // We still go on to try to complete the type independently, as it + // may also require instantiations or diagnostics if it remains + // incomplete. + } + } + } } /// \brief Ensure that the type of the given expression is complete. @@ -6250,87 +6421,26 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, /// /// \returns \c true if the type of \p E is incomplete and diagnosed, \c false /// otherwise. -bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){ +bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser) { QualType T = E->getType(); - // Fast path the case where the type is already complete. - if (!T->isIncompleteType()) - // FIXME: The definition might not be visible. - return false; - // Incomplete array types may be completed by the initializer attached to // their definitions. For static data members of class templates and for // variable templates, we need to instantiate the definition to get this // initializer and complete the type. if (T->isIncompleteArrayType()) { - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) { - if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) { - SourceLocation PointOfInstantiation = E->getExprLoc(); - - if (MemberSpecializationInfo *MSInfo = - Var->getMemberSpecializationInfo()) { - // If we don't already have a point of instantiation, this is it. - if (MSInfo->getPointOfInstantiation().isInvalid()) { - MSInfo->setPointOfInstantiation(PointOfInstantiation); - - // This is a modification of an existing AST node. Notify - // listeners. - if (ASTMutationListener *L = getASTMutationListener()) - L->StaticDataMemberInstantiated(Var); - } - } else { - VarTemplateSpecializationDecl *VarSpec = - cast<VarTemplateSpecializationDecl>(Var); - if (VarSpec->getPointOfInstantiation().isInvalid()) - VarSpec->setPointOfInstantiation(PointOfInstantiation); - } - - InstantiateVariableDefinition(PointOfInstantiation, Var); - - // Update the type to the newly instantiated definition's type both - // here and within the expression. - if (VarDecl *Def = Var->getDefinition()) { - DRE->setDecl(Def); - T = Def->getType(); - DRE->setType(T); - E->setType(T); - } - - // We still go on to try to complete the type independently, as it - // may also require instantiations or diagnostics if it remains - // incomplete. - } - } - } + completeExprArrayBound(E); + T = E->getType(); } // FIXME: Are there other cases which require instantiating something other // than the type to complete the type of an expression? - // Look through reference types and complete the referred type. - if (const ReferenceType *Ref = T->getAs<ReferenceType>()) - T = Ref->getPointeeType(); - return RequireCompleteType(E->getExprLoc(), T, Diagnoser); } -namespace { - struct TypeDiagnoserDiag : Sema::TypeDiagnoser { - unsigned DiagID; - - TypeDiagnoserDiag(unsigned DiagID) - : Sema::TypeDiagnoser(DiagID == 0), DiagID(DiagID) {} - - void diagnose(Sema &S, SourceLocation Loc, QualType T) override { - if (Suppressed) return; - S.Diag(Loc, DiagID) << T; - } - }; -} - bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) { - TypeDiagnoserDiag Diagnoser(DiagID); + BoundTypeDiagnoser<> Diagnoser(DiagID); return RequireCompleteExprType(E, Diagnoser); } @@ -6353,7 +6463,7 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) { /// @c false otherwise. bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser) { - if (RequireCompleteTypeImpl(Loc, T, Diagnoser)) + if (RequireCompleteTypeImpl(Loc, T, &Diagnoser)) return true; if (const TagType *Tag = T->getAs<TagType>()) { if (!Tag->getDecl()->isCompleteDefinitionRequired()) { @@ -6457,7 +6567,7 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { /// \brief The implementation of RequireCompleteType bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser) { + TypeDiagnoser *Diagnoser) { // FIXME: Add this assertion to make sure we always get instantiation points. // assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType"); // FIXME: Add this assertion to help us flush out problems with @@ -6466,24 +6576,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // assert(!T->isDependentType() && // "Can't ask whether a dependent type is complete"); + // We lock in the inheritance model once somebody has asked us to ensure + // that a pointer-to-member type is complete. + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) { + if (!MPTy->getClass()->isDependentType()) { + (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0)); + assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl()); + } + } + } + // If we have a complete type, we're done. NamedDecl *Def = nullptr; if (!T->isIncompleteType(&Def)) { // If we know about the definition but it is not visible, complain. NamedDecl *SuggestedDef = nullptr; - if (!Diagnoser.Suppressed && Def && - !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) - diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true); - - // We lock in the inheritance model once somebody has asked us to ensure - // that a pointer-to-member type is complete. - if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) { - if (!MPTy->getClass()->isDependentType()) { - RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0); - assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl()); - } - } + if (Def && + !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) { + // If the user is going to see an error here, recover by making the + // definition visible. + bool TreatAsComplete = Diagnoser && !isSFINAEContext(); + if (Diagnoser) + diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true, + /*Recover*/TreatAsComplete); + return !TreatAsComplete; } return false; @@ -6500,6 +6617,9 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // chain for a declaration that can be accessed through a mechanism other // than name lookup (eg, referenced in a template, or a variable whose type // could be completed by the module)? + // + // FIXME: Should we map through to the base array element type before + // checking for a tag type? if (Tag || IFace) { NamedDecl *D = Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl(); @@ -6530,12 +6650,16 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, = Context.getAsConstantArrayType(MaybeTemplate)) MaybeTemplate = Array->getElementType(); if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) { + bool Instantiated = false; + bool Diagnosed = false; if (ClassTemplateSpecializationDecl *ClassTemplateSpec = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) { - if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) - return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec, - TSK_ImplicitInstantiation, - /*Complain=*/!Diagnoser.Suppressed); + if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) { + Diagnosed = InstantiateClassTemplateSpecialization( + Loc, ClassTemplateSpec, TSK_ImplicitInstantiation, + /*Complain=*/Diagnoser); + Instantiated = true; + } } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Record->getDecl())) { CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass(); @@ -6543,16 +6667,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo(); assert(MSI && "Missing member specialization information?"); // This record was instantiated from a class within a template. - if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) - return InstantiateClass(Loc, Rec, Pattern, - getTemplateInstantiationArgs(Rec), - TSK_ImplicitInstantiation, - /*Complain=*/!Diagnoser.Suppressed); + if (MSI->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization) { + Diagnosed = InstantiateClass(Loc, Rec, Pattern, + getTemplateInstantiationArgs(Rec), + TSK_ImplicitInstantiation, + /*Complain=*/Diagnoser); + Instantiated = true; + } } } + + if (Instantiated) { + // Instantiate* might have already complained that the template is not + // defined, if we asked it to. + if (Diagnoser && Diagnosed) + return true; + // If we instantiated a definition, check that it's usable, even if + // instantiation produced an error, so that repeated calls to this + // function give consistent answers. + if (!T->isIncompleteType()) + return RequireCompleteTypeImpl(Loc, T, Diagnoser); + } } - if (Diagnoser.Suppressed) + if (!Diagnoser) return true; // We have an incomplete type. Produce a diagnostic. @@ -6562,7 +6701,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, return true; } - Diagnoser.diagnose(*this, Loc, T); + Diagnoser->diagnose(*this, Loc, T); // If the type was a forward declaration of a class/struct/union // type, produce a note. @@ -6586,7 +6725,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID) { - TypeDiagnoserDiag Diagnoser(DiagID); + BoundTypeDiagnoser<> Diagnoser(DiagID); return RequireCompleteType(Loc, T, Diagnoser); } @@ -6627,14 +6766,10 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, assert(!T->isDependentType() && "type should not be dependent"); QualType ElemType = Context.getBaseElementType(T); - RequireCompleteType(Loc, ElemType, 0); - - if (T->isLiteralType(Context)) + if ((isCompleteType(Loc, ElemType) || ElemType->isVoidType()) && + T->isLiteralType(Context)) return false; - if (Diagnoser.Suppressed) - return true; - Diagnoser.diagnose(*this, Loc, T); if (T->isVariableArrayType()) @@ -6649,10 +6784,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, // A partially-defined class type can't be a literal type, because a literal // class type must have a trivial destructor (which can't be checked until // the class definition is complete). - if (!RD->isCompleteDefinition()) { - RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T); + if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T)) return true; - } // If the class has virtual base classes, then it's not an aggregate, and // cannot have any constexpr constructors or a trivial default constructor, @@ -6704,7 +6837,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, } bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) { - TypeDiagnoserDiag Diagnoser(DiagID); + BoundTypeDiagnoser<> Diagnoser(DiagID); return RequireLiteralType(Loc, T, Diagnoser); } @@ -6730,6 +6863,9 @@ QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) { if (ER.isInvalid()) return QualType(); E = ER.get(); + if (!getLangOpts().CPlusPlus && E->refersToBitField()) + Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2; + if (!E->isTypeDependent()) { QualType T = E->getType(); if (const TagType *TT = T->getAs<TagType>()) diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index 6e193a3..e0a9653 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -21,6 +21,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" @@ -390,7 +391,7 @@ public: /// due to transformation. /// /// \returns true if an error occurred, false otherwise. - bool TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall, + bool TransformExprs(Expr *const *Inputs, unsigned NumInputs, bool IsCall, SmallVectorImpl<Expr *> &Outputs, bool *ArgChanged = nullptr); @@ -503,7 +504,8 @@ public: /// /// Returns true if there was an error. bool TransformTemplateArgument(const TemplateArgumentLoc &Input, - TemplateArgumentLoc &Output); + TemplateArgumentLoc &Output, + bool Uneval = false); /// \brief Transform the given set of template arguments. /// @@ -525,8 +527,10 @@ public: /// Returns true if an error occurred. bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs, unsigned NumInputs, - TemplateArgumentListInfo &Outputs) { - return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs); + TemplateArgumentListInfo &Outputs, + bool Uneval = false) { + return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs, + Uneval); } /// \brief Transform the given set of template arguments. @@ -546,7 +550,8 @@ public: template<typename InputIterator> bool TransformTemplateArguments(InputIterator First, InputIterator Last, - TemplateArgumentListInfo &Outputs); + TemplateArgumentListInfo &Outputs, + bool Uneval = false); /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument. void InventTemplateArgumentLoc(const TemplateArgument &Arg, @@ -843,11 +848,11 @@ public: /// \brief Build a new C++11 auto type. /// /// By default, builds a new AutoType with the given deduced type. - QualType RebuildAutoType(QualType Deduced, bool IsDecltypeAuto) { + QualType RebuildAutoType(QualType Deduced, AutoTypeKeyword Keyword) { // Note, IsDependent is always false here: we implicitly convert an 'auto' // which has been deduced to a dependent type into an undeduced 'auto', so // that we'll retry deduction after the transformation. - return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto, + return SemaRef.Context.getAutoType(Deduced, Keyword, /*IsDependent*/ false); } @@ -1282,6 +1287,30 @@ public: Constraints, Clobbers, Exprs, EndLoc); } + /// \brief Build a new co_return statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCoreturnStmt(SourceLocation CoreturnLoc, Expr *Result) { + return getSema().BuildCoreturnStmt(CoreturnLoc, Result); + } + + /// \brief Build a new co_await expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCoawaitExpr(SourceLocation CoawaitLoc, Expr *Result) { + return getSema().BuildCoawaitExpr(CoawaitLoc, Result); + } + + /// \brief Build a new co_yield expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCoyieldExpr(SourceLocation CoyieldLoc, Expr *Result) { + return getSema().BuildCoyieldExpr(CoyieldLoc, Result); + } + /// \brief Build a new Objective-C \@try statement. /// /// By default, performs semantic analysis to build the new statement. @@ -1354,12 +1383,15 @@ public: /// /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. - OMPClause *RebuildOMPIfClause(Expr *Condition, - SourceLocation StartLoc, + OMPClause *RebuildOMPIfClause(OpenMPDirectiveKind NameModifier, + Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation NameModifierLoc, + SourceLocation ColonLoc, SourceLocation EndLoc) { - return getSema().ActOnOpenMPIfClause(Condition, StartLoc, - LParenLoc, EndLoc); + return getSema().ActOnOpenMPIfClause(NameModifier, Condition, StartLoc, + LParenLoc, NameModifierLoc, ColonLoc, + EndLoc); } /// \brief Build a new OpenMP 'final' clause. @@ -1395,6 +1427,16 @@ public: return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc); } + /// \brief Build a new OpenMP 'simdlen' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPSimdlenClause(Expr *Len, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc); + } + /// \brief Build a new OpenMP 'collapse' clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -1436,15 +1478,24 @@ public: /// /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. - OMPClause *RebuildOMPScheduleClause(OpenMPScheduleClauseKind Kind, - Expr *ChunkSize, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation KindLoc, - SourceLocation CommaLoc, - SourceLocation EndLoc) { + OMPClause *RebuildOMPScheduleClause( + OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, + OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, + SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) { return getSema().ActOnOpenMPScheduleClause( - Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc); + M1, M2, Kind, ChunkSize, StartLoc, LParenLoc, M1Loc, M2Loc, KindLoc, + CommaLoc, EndLoc); + } + + /// \brief Build a new OpenMP 'ordered' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPOrderedClause(SourceLocation StartLoc, + SourceLocation EndLoc, + SourceLocation LParenLoc, Expr *Num) { + return getSema().ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Num); } /// \brief Build a new OpenMP 'private' clause. @@ -1518,10 +1569,13 @@ public: OMPClause *RebuildOMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, + OpenMPLinearClauseKind Modifier, + SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc) { return getSema().ActOnOpenMPLinearClause(VarList, Step, StartLoc, LParenLoc, - ColonLoc, EndLoc); + Modifier, ModifierLoc, ColonLoc, + EndLoc); } /// \brief Build a new OpenMP 'aligned' clause. @@ -1586,6 +1640,97 @@ public: StartLoc, LParenLoc, EndLoc); } + /// \brief Build a new OpenMP 'device' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPDeviceClause(Expr *Device, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPDeviceClause(Device, StartLoc, LParenLoc, + EndLoc); + } + + /// \brief Build a new OpenMP 'map' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPMapClause( + OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType, + SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPMapClause(MapTypeModifier, MapType, MapLoc, + ColonLoc, VarList,StartLoc, + LParenLoc, EndLoc); + } + + /// \brief Build a new OpenMP 'num_teams' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPNumTeamsClause(NumTeams, StartLoc, LParenLoc, + EndLoc); + } + + /// \brief Build a new OpenMP 'thread_limit' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPThreadLimitClause(Expr *ThreadLimit, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPThreadLimitClause(ThreadLimit, StartLoc, + LParenLoc, EndLoc); + } + + /// \brief Build a new OpenMP 'priority' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPPriorityClause(Expr *Priority, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPPriorityClause(Priority, StartLoc, LParenLoc, + EndLoc); + } + + /// \brief Build a new OpenMP 'grainsize' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPGrainsizeClause(Expr *Grainsize, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPGrainsizeClause(Grainsize, StartLoc, LParenLoc, + EndLoc); + } + + /// \brief Build a new OpenMP 'num_tasks' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPNumTasksClause(NumTasks, StartLoc, LParenLoc, + EndLoc); + } + + /// \brief Build a new OpenMP 'hint' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPHintClause(Expr *Hint, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc); + } + /// \brief Rebuild the operand to an Objective-C \@synchronized statement. /// /// By default, performs semantic analysis to build the new statement. @@ -1673,6 +1818,7 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation CoawaitLoc, SourceLocation ColonLoc, Stmt *Range, Stmt *BeginEnd, Expr *Cond, Expr *Inc, @@ -1695,7 +1841,8 @@ public: } } - return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd, + return getSema().BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc, + Range, BeginEnd, Cond, Inc, LoopVar, RParenLoc, Sema::BFRK_Rebuild); } @@ -1808,12 +1955,11 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildOffsetOfExpr(SourceLocation OperatorLoc, - TypeSourceInfo *Type, - Sema::OffsetOfComponent *Components, - unsigned NumComponents, - SourceLocation RParenLoc) { + TypeSourceInfo *Type, + ArrayRef<Sema::OffsetOfComponent> Components, + SourceLocation RParenLoc) { return getSema().BuildBuiltinOffsetOf(OperatorLoc, Type, Components, - NumComponents, RParenLoc); + RParenLoc); } /// \brief Build a new sizeof, alignof or vec_step expression with a @@ -1857,6 +2003,18 @@ public: RBracketLoc); } + /// \brief Build a new array section expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildOMPArraySectionExpr(Expr *Base, SourceLocation LBracketLoc, + Expr *LowerBound, + SourceLocation ColonLoc, Expr *Length, + SourceLocation RBracketLoc) { + return getSema().ActOnOMPArraySectionExpr(Base, LBracketLoc, LowerBound, + ColonLoc, Length, RBracketLoc); + } + /// \brief Build a new call expression. /// /// By default, performs semantic analysis to build the new expression. @@ -1921,7 +2079,8 @@ public: return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow, SS, TemplateKWLoc, FirstQualifierInScope, - R, ExplicitTemplateArgs); + R, ExplicitTemplateArgs, + /*S*/nullptr); } /// \brief Build a new binary operator expression. @@ -1987,7 +2146,8 @@ public: SS, SourceLocation(), /*FirstQualifierInScope*/ nullptr, NameInfo, - /* TemplateArgs */ nullptr); + /* TemplateArgs */ nullptr, + /*S*/ nullptr); } /// \brief Build a new initializer list expression. @@ -2435,7 +2595,7 @@ public: TemplateArgs); return getSema().BuildQualifiedDeclarationNameExpr( - SS, NameInfo, IsAddressOfOperand, RecoveryTSI); + SS, NameInfo, IsAddressOfOperand, /*S*/nullptr, RecoveryTSI); } /// \brief Build a new template-id expression. @@ -2529,7 +2689,7 @@ public: SS, TemplateKWLoc, FirstQualifierInScope, MemberNameInfo, - TemplateArgs); + TemplateArgs, /*S*/nullptr); } /// \brief Build a new member reference expression. @@ -2551,7 +2711,7 @@ public: OperatorLoc, IsArrow, SS, TemplateKWLoc, FirstQualifierInScope, - R, TemplateArgs); + R, TemplateArgs, /*S*/nullptr); } /// \brief Build a new noexcept expression. @@ -2563,18 +2723,14 @@ public: } /// \brief Build a new expression to compute the length of a parameter pack. - ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack, + ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, + NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, - Optional<unsigned> Length) { - if (Length) - return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), - OperatorLoc, Pack, PackLoc, - RParenLoc, *Length); - - return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), - OperatorLoc, Pack, PackLoc, - RParenLoc); + Optional<unsigned> Length, + ArrayRef<TemplateArgument> PartialArgs) { + return SizeOfPackExpr::Create(SemaRef.Context, OperatorLoc, Pack, PackLoc, + RParenLoc, Length, PartialArgs); } /// \brief Build a new Objective-C boxed expression. @@ -2608,9 +2764,8 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildObjCDictionaryLiteral(SourceRange Range, - ObjCDictionaryElement *Elements, - unsigned NumElements) { - return getSema().BuildObjCDictionaryLiteral(Range, Elements, NumElements); + MutableArrayRef<ObjCDictionaryElement> Elements) { + return getSema().BuildObjCDictionaryLiteral(Range, Elements); } /// \brief Build a new Objective-C \@encode expression. @@ -2657,20 +2812,18 @@ public: ExprResult RebuildObjCMessageExpr(SourceLocation SuperLoc, Selector Sel, ArrayRef<SourceLocation> SelectorLocs, + QualType SuperType, 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, + SuperType, SuperLoc, Sel, Method, LBracLoc, SelectorLocs, RBracLoc, Args) : SemaRef.BuildClassMessage(nullptr, - ReceiverTy, + SuperType, SuperLoc, Sel, Method, LBracLoc, SelectorLocs, RBracLoc, Args); @@ -2693,7 +2846,8 @@ public: SS, SourceLocation(), /*FirstQualifierInScope=*/nullptr, NameInfo, - /*TemplateArgs=*/nullptr); + /*TemplateArgs=*/nullptr, + /*S=*/nullptr); } /// \brief Build a new Objective-C property reference expression. @@ -2711,7 +2865,8 @@ public: SS, SourceLocation(), /*FirstQualifierInScope=*/nullptr, NameInfo, - /*TemplateArgs=*/nullptr); + /*TemplateArgs=*/nullptr, + /*S=*/nullptr); } /// \brief Build a new Objective-C property reference expression. @@ -2743,7 +2898,8 @@ public: SS, SourceLocation(), /*FirstQualifierInScope=*/nullptr, NameInfo, - /*TemplateArgs=*/nullptr); + /*TemplateArgs=*/nullptr, + /*S=*/nullptr); } /// \brief Build a new shuffle vector expression. @@ -3043,7 +3199,7 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init, } template<typename Derived> -bool TreeTransform<Derived>::TransformExprs(Expr **Inputs, +bool TreeTransform<Derived>::TransformExprs(Expr *const *Inputs, unsigned NumInputs, bool IsCall, SmallVectorImpl<Expr *> &Outputs, @@ -3458,7 +3614,7 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc( template<typename Derived> bool TreeTransform<Derived>::TransformTemplateArgument( const TemplateArgumentLoc &Input, - TemplateArgumentLoc &Output) { + TemplateArgumentLoc &Output, bool Uneval) { const TemplateArgument &Arg = Input.getArgument(); switch (Arg.getKind()) { case TemplateArgument::Null: @@ -3506,8 +3662,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument( case TemplateArgument::Expression: { // Template argument expressions are constant expressions. - EnterExpressionEvaluationContext Unevaluated(getSema(), - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + getSema(), Uneval ? Sema::Unevaluated : Sema::ConstantEvaluated); Expr *InputExpr = Input.getSourceExpression(); if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); @@ -3585,9 +3741,9 @@ public: template<typename Derived> template<typename InputIterator> -bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, - InputIterator Last, - TemplateArgumentListInfo &Outputs) { +bool TreeTransform<Derived>::TransformTemplateArguments( + InputIterator First, InputIterator Last, TemplateArgumentListInfo &Outputs, + bool Uneval) { for (; First != Last; ++First) { TemplateArgumentLoc Out; TemplateArgumentLoc In = *First; @@ -3605,7 +3761,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, In.getArgument().pack_begin()), PackLocIterator(*this, In.getArgument().pack_end()), - Outputs)) + Outputs, Uneval)) return true; continue; @@ -3643,7 +3799,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, // expansion. TemplateArgumentLoc OutPattern; Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); - if (getDerived().TransformTemplateArgument(Pattern, OutPattern)) + if (getDerived().TransformTemplateArgument(Pattern, OutPattern, Uneval)) return true; Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis, @@ -3660,7 +3816,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); - if (getDerived().TransformTemplateArgument(Pattern, Out)) + if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval)) return true; if (Out.getArgument().containsUnexpandedParameterPack()) { @@ -3678,7 +3834,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, if (RetainExpansion) { ForgetPartiallySubstitutedPackRAII Forget(getDerived()); - if (getDerived().TransformTemplateArgument(Pattern, Out)) + if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval)) return true; Out = getDerived().RebuildPackExpansion(Out, Ellipsis, @@ -3693,7 +3849,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, } // The simple case: - if (getDerived().TransformTemplateArgument(In, Out)) + if (getDerived().TransformTemplateArgument(In, Out, Uneval)) return true; Outputs.addArgument(Out); @@ -3810,7 +3966,7 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, Qs.removeObjCLifetime(); Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(), Qs); - Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(), + Result = SemaRef.Context.getAutoType(Deduced, AutoTy->getKeyword(), AutoTy->isDependentType()); TLB.TypeWasModifiedSafely(Result); } else { @@ -4700,9 +4856,7 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType( QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType() || - T->getNumParams() != ParamTypes.size() || - !std::equal(T->param_type_begin(), T->param_type_end(), - ParamTypes.begin()) || EPIChanged) { + T->getParamTypes() != llvm::makeArrayRef(ParamTypes) || EPIChanged) { Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, EPI); if (Result.isNull()) return QualType(); @@ -5015,7 +5169,7 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB, QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced || T->isDependentType()) { - Result = getDerived().RebuildAutoType(NewDeduced, T->isDecltypeAuto()); + Result = getDerived().RebuildAutoType(NewDeduced, T->getKeyword()); if (Result.isNull()) return QualType(); } @@ -6119,6 +6273,11 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) { if (Init.isInvalid()) return StmtError(); + // In OpenMP loop region loop control variable must be captured and be + // private. Perform analysis of first part (if any). + if (getSema().getLangOpts().OpenMP && Init.isUsable()) + getSema().ActOnOpenMPLoopInitialization(S->getForLoc(), Init.get()); + // Transform the condition ExprResult Cond; VarDecl *ConditionVar = nullptr; @@ -6351,6 +6510,56 @@ TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) { TransformedExprs, S->getEndLoc()); } +// C++ Coroutines TS + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) { + // The coroutine body should be re-formed by the caller if necessary. + return getDerived().TransformStmt(S->getBody()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCoreturnStmt(CoreturnStmt *S) { + ExprResult Result = getDerived().TransformInitializer(S->getOperand(), + /*NotCopyInit*/false); + if (Result.isInvalid()) + return StmtError(); + + // Always rebuild; we don't know if this needs to be injected into a new + // context or if the promise type has changed. + return getDerived().RebuildCoreturnStmt(S->getKeywordLoc(), Result.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCoawaitExpr(CoawaitExpr *E) { + ExprResult Result = getDerived().TransformInitializer(E->getOperand(), + /*NotCopyInit*/false); + if (Result.isInvalid()) + return ExprError(); + + // Always rebuild; we don't know if this needs to be injected into a new + // context or if the promise type has changed. + return getDerived().RebuildCoawaitExpr(E->getKeywordLoc(), Result.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCoyieldExpr(CoyieldExpr *E) { + ExprResult Result = getDerived().TransformInitializer(E->getOperand(), + /*NotCopyInit*/false); + if (Result.isInvalid()) + return ExprError(); + + // Always rebuild; we don't know if this needs to be injected into a new + // context or if the promise type has changed. + return getDerived().RebuildCoyieldExpr(E->getKeywordLoc(), Result.get()); +} + +// Objective-C Statements. + template<typename Derived> StmtResult TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) { @@ -6640,6 +6849,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { Inc.get() != S->getInc() || LoopVar.get() != S->getLoopVarStmt()) { NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), + S->getCoawaitLoc(), S->getColonLoc(), Range.get(), BeginEnd.get(), Cond.get(), Inc.get(), LoopVar.get(), @@ -6656,6 +6866,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { // it now so we have a new statement to attach the body to. if (Body.get() != S->getBody() && NewStmt.get() == S) { NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), + S->getCoawaitLoc(), S->getColonLoc(), Range.get(), BeginEnd.get(), Cond.get(), Inc.get(), LoopVar.get(), @@ -6766,6 +6977,25 @@ TreeTransform<Derived>::TransformMSPropertyRefExpr(MSPropertyRefExpr *E) { } template <typename Derived> +ExprResult TreeTransform<Derived>::TransformMSPropertySubscriptExpr( + MSPropertySubscriptExpr *E) { + auto BaseRes = getDerived().TransformExpr(E->getBase()); + if (BaseRes.isInvalid()) + return ExprError(); + auto IdxRes = getDerived().TransformExpr(E->getIdx()); + if (IdxRes.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + BaseRes.get() == E->getBase() && + IdxRes.get() == E->getIdx()) + return E; + + return getDerived().RebuildArraySubscriptExpr( + BaseRes.get(), SourceLocation(), IdxRes.get(), E->getRBracketLoc()); +} + +template <typename Derived> StmtResult TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) { StmtResult TryBlock = getDerived().TransformCompoundStmt(S->getTryBlock()); if (TryBlock.isInvalid()) @@ -6844,10 +7074,7 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective( } } StmtResult AssociatedStmt; - if (D->hasAssociatedStmt()) { - if (!D->getAssociatedStmt()) { - return StmtError(); - } + if (D->hasAssociatedStmt() && D->getAssociatedStmt()) { getDerived().getSema().ActOnOpenMPRegionStart(D->getDirectiveKind(), /*CurScope=*/nullptr); StmtResult Body; @@ -7115,6 +7342,17 @@ TreeTransform<Derived>::TransformOMPTargetDirective(OMPTargetDirective *D) { } template <typename Derived> +StmtResult TreeTransform<Derived>::TransformOMPTargetDataDirective( + OMPTargetDataDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_target_data, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + +template <typename Derived> StmtResult TreeTransform<Derived>::TransformOMPTeamsDirective(OMPTeamsDirective *D) { DeclarationNameInfo DirName; @@ -7147,6 +7385,39 @@ TreeTransform<Derived>::TransformOMPCancelDirective(OMPCancelDirective *D) { return Res; } +template <typename Derived> +StmtResult +TreeTransform<Derived>::TransformOMPTaskLoopDirective(OMPTaskLoopDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformOMPTaskLoopSimdDirective( + OMPTaskLoopSimdDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop_simd, DirName, + nullptr, D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformOMPDistributeDirective( + OMPDistributeDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_distribute, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + //===----------------------------------------------------------------------===// // OpenMP clause transformation //===----------------------------------------------------------------------===// @@ -7155,8 +7426,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) { ExprResult Cond = getDerived().TransformExpr(C->getCondition()); if (Cond.isInvalid()) return nullptr; - return getDerived().RebuildOMPIfClause(Cond.get(), C->getLocStart(), - C->getLParenLoc(), C->getLocEnd()); + return getDerived().RebuildOMPIfClause( + C->getNameModifier(), Cond.get(), C->getLocStart(), C->getLParenLoc(), + C->getNameModifierLoc(), C->getColonLoc(), C->getLocEnd()); } template <typename Derived> @@ -7190,10 +7462,20 @@ TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) { template <typename Derived> OMPClause * +TreeTransform<Derived>::TransformOMPSimdlenClause(OMPSimdlenClause *C) { + ExprResult E = getDerived().TransformExpr(C->getSimdlen()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPSimdlenClause( + E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); +} + +template <typename Derived> +OMPClause * TreeTransform<Derived>::TransformOMPCollapseClause(OMPCollapseClause *C) { ExprResult E = getDerived().TransformExpr(C->getNumForLoops()); if (E.isInvalid()) - return 0; + return nullptr; return getDerived().RebuildOMPCollapseClause( E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); } @@ -7221,15 +7503,23 @@ TreeTransform<Derived>::TransformOMPScheduleClause(OMPScheduleClause *C) { if (E.isInvalid()) return nullptr; return getDerived().RebuildOMPScheduleClause( + C->getFirstScheduleModifier(), C->getSecondScheduleModifier(), C->getScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(), + C->getFirstScheduleModifierLoc(), C->getSecondScheduleModifierLoc(), C->getScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd()); } template <typename Derived> OMPClause * TreeTransform<Derived>::TransformOMPOrderedClause(OMPOrderedClause *C) { - // No need to rebuild this clause, no template-dependent parameters. - return C; + ExprResult E; + if (auto *Num = C->getNumForLoops()) { + E = getDerived().TransformExpr(Num); + if (E.isInvalid()) + return nullptr; + } + return getDerived().RebuildOMPOrderedClause(C->getLocStart(), C->getLocEnd(), + C->getLParenLoc(), E.get()); } template <typename Derived> @@ -7288,6 +7578,26 @@ TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) { template <typename Derived> OMPClause * +TreeTransform<Derived>::TransformOMPThreadsClause(OMPThreadsClause *C) { + // No need to rebuild this clause, no template-dependent parameters. + return C; +} + +template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPSIMDClause(OMPSIMDClause *C) { + // No need to rebuild this clause, no template-dependent parameters. + return C; +} + +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPNogroupClause(OMPNogroupClause *C) { + // No need to rebuild this clause, no template-dependent parameters. + return C; +} + +template <typename Derived> +OMPClause * TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) { llvm::SmallVector<Expr *, 16> Vars; Vars.reserve(C->varlist_size()); @@ -7385,9 +7695,9 @@ TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) { ExprResult Step = getDerived().TransformExpr(C->getStep()); if (Step.isInvalid()) return nullptr; - return getDerived().RebuildOMPLinearClause(Vars, Step.get(), C->getLocStart(), - C->getLParenLoc(), - C->getColonLoc(), C->getLocEnd()); + return getDerived().RebuildOMPLinearClause( + Vars, Step.get(), C->getLocStart(), C->getLParenLoc(), C->getModifier(), + C->getModifierLoc(), C->getColonLoc(), C->getLocEnd()); } template <typename Derived> @@ -7469,6 +7779,91 @@ TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) { C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); } +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPDeviceClause(OMPDeviceClause *C) { + ExprResult E = getDerived().TransformExpr(C->getDevice()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPDeviceClause( + E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); +} + +template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) { + llvm::SmallVector<Expr *, 16> Vars; + Vars.reserve(C->varlist_size()); + for (auto *VE : C->varlists()) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE)); + if (EVar.isInvalid()) + return nullptr; + Vars.push_back(EVar.get()); + } + return getDerived().RebuildOMPMapClause( + C->getMapTypeModifier(), C->getMapType(), C->getMapLoc(), + C->getColonLoc(), Vars, C->getLocStart(), C->getLParenLoc(), + C->getLocEnd()); +} + +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPNumTeamsClause(OMPNumTeamsClause *C) { + ExprResult E = getDerived().TransformExpr(C->getNumTeams()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPNumTeamsClause( + E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); +} + +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPThreadLimitClause(OMPThreadLimitClause *C) { + ExprResult E = getDerived().TransformExpr(C->getThreadLimit()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPThreadLimitClause( + E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); +} + +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPPriorityClause(OMPPriorityClause *C) { + ExprResult E = getDerived().TransformExpr(C->getPriority()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPPriorityClause( + E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); +} + +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPGrainsizeClause(OMPGrainsizeClause *C) { + ExprResult E = getDerived().TransformExpr(C->getGrainsize()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPGrainsizeClause( + E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); +} + +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPNumTasksClause(OMPNumTasksClause *C) { + ExprResult E = getDerived().TransformExpr(C->getNumTasks()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPNumTasksClause( + E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); +} + +template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPHintClause(OMPHintClause *C) { + ExprResult E = getDerived().TransformExpr(C->getHint()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPHintClause(E.get(), C->getLocStart(), + C->getLParenLoc(), C->getLocEnd()); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// @@ -7668,16 +8063,15 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) { // template code that we don't care. bool ExprChanged = false; typedef Sema::OffsetOfComponent Component; - typedef OffsetOfExpr::OffsetOfNode Node; SmallVector<Component, 4> Components; for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { - const Node &ON = E->getComponent(I); + const OffsetOfNode &ON = E->getComponent(I); Component Comp; Comp.isBrackets = true; Comp.LocStart = ON.getSourceRange().getBegin(); Comp.LocEnd = ON.getSourceRange().getEnd(); switch (ON.getKind()) { - case Node::Array: { + case OffsetOfNode::Array: { Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex()); ExprResult Index = getDerived().TransformExpr(FromIndex); if (Index.isInvalid()) @@ -7689,8 +8083,8 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) { break; } - case Node::Field: - case Node::Identifier: + case OffsetOfNode::Field: + case OffsetOfNode::Identifier: Comp.isBrackets = false; Comp.U.IdentInfo = ON.getFieldName(); if (!Comp.U.IdentInfo) @@ -7698,7 +8092,7 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) { break; - case Node::Base: + case OffsetOfNode::Base: // Will be recomputed during the rebuild. continue; } @@ -7714,14 +8108,13 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) { // Build a new offsetof expression. return getDerived().RebuildOffsetOfExpr(E->getOperatorLoc(), Type, - Components.data(), Components.size(), - E->getRParenLoc()); + Components, E->getRParenLoc()); } template<typename Derived> ExprResult TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) { - assert(getDerived().AlreadyTransformed(E->getType()) && + assert((!E->getSourceExpr() || getDerived().AlreadyTransformed(E->getType())) && "opaque value expression requires transformation"); return E; } @@ -7829,6 +8222,36 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) { E->getRBracketLoc()); } +template <typename Derived> +ExprResult +TreeTransform<Derived>::TransformOMPArraySectionExpr(OMPArraySectionExpr *E) { + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + ExprResult LowerBound; + if (E->getLowerBound()) { + LowerBound = getDerived().TransformExpr(E->getLowerBound()); + if (LowerBound.isInvalid()) + return ExprError(); + } + + ExprResult Length; + if (E->getLength()) { + Length = getDerived().TransformExpr(E->getLength()); + if (Length.isInvalid()) + return ExprError(); + } + + if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() && + LowerBound.get() == E->getLowerBound() && Length.get() == E->getLength()) + return E; + + return getDerived().RebuildOMPArraySectionExpr( + Base.get(), E->getBase()->getLocEnd(), LowerBound.get(), E->getColonLoc(), + Length.get(), E->getRBracketLoc()); +} + template<typename Derived> ExprResult TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { @@ -8995,9 +9418,20 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc(); // If we have neither explicit template arguments, nor the template keyword, - // it's a normal declaration name. - if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) + // it's a normal declaration name or member reference. + if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) { + NamedDecl *D = R.getAsSingle<NamedDecl>(); + // In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an + // instance member. In other contexts, BuildPossibleImplicitMemberExpr will + // give a good diagnostic. + if (D && D->isCXXInstanceMember()) { + return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, + /*TemplateArgs=*/nullptr, + /*Scope=*/nullptr); + } + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + } // If we have template arguments, rebuild them, then rebuild the // templateid expression. @@ -9404,9 +9838,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { VarDecl *OldVD = C->getCapturedVar(); QualType NewInitCaptureType = - getSema().performLambdaInitCaptureInitialization(C->getLocation(), - OldVD->getType()->isReferenceType(), OldVD->getIdentifier(), - NewExprInit); + getSema().buildLambdaInitCaptureInitialization( + C->getLocation(), OldVD->getType()->isReferenceType(), + OldVD->getIdentifier(), + C->getCapturedVar()->getInitStyle() != VarDecl::CInit, NewExprInit); NewExprInitResult = NewExprInit; InitCaptureExprsAndTypes[C - E->capture_begin()] = std::make_pair(NewExprInitResult, NewInitCaptureType); @@ -9513,8 +9948,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { } VarDecl *OldVD = C->getCapturedVar(); VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl( - OldVD->getLocation(), InitExprTypePair.second, - OldVD->getIdentifier(), Init.get()); + OldVD->getLocation(), InitExprTypePair.second, OldVD->getIdentifier(), + OldVD->getInitStyle(), Init.get()); if (!NewVD) Invalid = true; else { @@ -9886,36 +10321,86 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { if (!E->isValueDependent()) return E; - // Note: None of the implementations of TryExpandParameterPacks can ever - // produce a diagnostic when given only a single unexpanded parameter pack, - // so - UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc()); - bool ShouldExpand = false; - bool RetainExpansion = false; - Optional<unsigned> NumExpansions; - if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), - Unexpanded, - ShouldExpand, RetainExpansion, - NumExpansions)) - return ExprError(); + EnterExpressionEvaluationContext Unevaluated(getSema(), Sema::Unevaluated); - if (RetainExpansion) - return E; + ArrayRef<TemplateArgument> PackArgs; + TemplateArgument ArgStorage; - NamedDecl *Pack = E->getPack(); - if (!ShouldExpand) { - Pack = cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getPackLoc(), - Pack)); + // Find the argument list to transform. + if (E->isPartiallySubstituted()) { + PackArgs = E->getPartialArguments(); + } else if (E->isValueDependent()) { + UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc()); + bool ShouldExpand = false; + bool RetainExpansion = false; + Optional<unsigned> NumExpansions; + if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), + Unexpanded, + ShouldExpand, RetainExpansion, + NumExpansions)) + return ExprError(); + + // If we need to expand the pack, build a template argument from it and + // expand that. + if (ShouldExpand) { + auto *Pack = E->getPack(); + if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Pack)) { + ArgStorage = getSema().Context.getPackExpansionType( + getSema().Context.getTypeDeclType(TTPD), None); + } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Pack)) { + ArgStorage = TemplateArgument(TemplateName(TTPD), None); + } else { + auto *VD = cast<ValueDecl>(Pack); + ExprResult DRE = getSema().BuildDeclRefExpr(VD, VD->getType(), + VK_RValue, E->getPackLoc()); + if (DRE.isInvalid()) + return ExprError(); + ArgStorage = new (getSema().Context) PackExpansionExpr( + getSema().Context.DependentTy, DRE.get(), E->getPackLoc(), None); + } + PackArgs = ArgStorage; + } + } + + // If we're not expanding the pack, just transform the decl. + if (!PackArgs.size()) { + auto *Pack = cast_or_null<NamedDecl>( + getDerived().TransformDecl(E->getPackLoc(), E->getPack())); if (!Pack) return ExprError(); + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack, + E->getPackLoc(), + E->getRParenLoc(), None, None); } + TemplateArgumentListInfo TransformedPackArgs(E->getPackLoc(), + E->getPackLoc()); + { + TemporaryBase Rebase(*this, E->getPackLoc(), getBaseEntity()); + typedef TemplateArgumentLocInventIterator< + Derived, const TemplateArgument*> PackLocIterator; + if (TransformTemplateArguments(PackLocIterator(*this, PackArgs.begin()), + PackLocIterator(*this, PackArgs.end()), + TransformedPackArgs, /*Uneval*/true)) + return ExprError(); + } - // We now know the length of the parameter pack, so build a new expression - // that stores that length. - return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack, + SmallVector<TemplateArgument, 8> Args; + bool PartialSubstitution = false; + for (auto &Loc : TransformedPackArgs.arguments()) { + Args.push_back(Loc.getArgument()); + if (Loc.getArgument().isPackExpansion()) + PartialSubstitution = true; + } + + if (PartialSubstitution) + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(), + E->getPackLoc(), + E->getRParenLoc(), None, Args); + + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(), E->getPackLoc(), E->getRParenLoc(), - NumExpansions); + Args.size(), None); } template<typename Derived> @@ -10242,8 +10727,7 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral( return SemaRef.MaybeBindToTemporary(E); return getDerived().RebuildObjCDictionaryLiteral(E->getSourceRange(), - Elements.data(), - Elements.size()); + Elements); } template<typename Derived> @@ -10337,6 +10821,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { return getDerived().RebuildObjCMessageExpr(E->getSuperLoc(), E->getSelector(), SelLocs, + E->getReceiverType(), E->getMethodDecl(), E->getLeftLoc(), Args, @@ -11075,7 +11560,8 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, SS, TemplateKWLoc, /*FIXME: FirstQualifier*/ nullptr, NameInfo, - /*TemplateArgs*/ nullptr); + /*TemplateArgs*/ nullptr, + /*S*/nullptr); } template<typename Derived> @@ -11114,4 +11600,4 @@ TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) { } // end namespace clang -#endif +#endif // LLVM_CLANG_LIB_SEMA_TREETRANSFORM_H |