diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8b7d651594f55..cb47d2a01b8e9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8756,7 +8756,8 @@ class Sema final : public SemaBase { ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, - const CXXScopeSpec &SS, FieldDecl *Field, + const NestedNameSpecifierLoc &NNS, + FieldDecl *Field, QualType FieldType, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo); @@ -8767,7 +8768,8 @@ class Sema final : public SemaBase { const CXXScopeSpec &SS, SourceLocation nameLoc, IndirectFieldDecl *indirectField, DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none), - Expr *baseObjectExpr = nullptr, SourceLocation opLoc = SourceLocation()); + Expr *baseObjectExpr = nullptr, const Type *BaseType = nullptr, + SourceLocation opLoc = SourceLocation()); private: void CheckMemberAccessOfNoDeref(const MemberExpr *E); @@ -13999,6 +14001,16 @@ class Sema final : public SemaBase { FunctionDecl *Spaceship); QualType resugar(const NestedNameSpecifier *NNS, QualType T); + QualType resugar(const NestedNameSpecifier *NNS, NamedDecl *ND, + ArrayRef Args, QualType T); + QualType resugar(NamedDecl *ND, ArrayRef Args, QualType T); + QualType resugar(const Type *Base, const NestedNameSpecifier *FieldNNS, + QualType T); + QualType resugar(const Type *Base, const NestedNameSpecifier *FieldNNS, + NamedDecl *ND, ArrayRef Args, QualType T); + QualType resugar(const Type *Base, QualType T); + QualType resugar(const Type *Base, NamedDecl *ND, + ArrayRef Args, QualType T); /// Performs template instantiation for all implicit template /// instantiations we have seen until this point. diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index db61af1495793..974bf3b018c09 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -649,9 +649,11 @@ struct BuiltinDumpStructGenerator { if (!FD || FD->isUnnamedBitField() || FD->isAnonymousStructOrUnion()) continue; + QualType FieldType = FD->getType(); + llvm::SmallString<20> Format = llvm::StringRef("%s%s %s "); llvm::SmallVector Args = {FieldIndentArg, - getTypeString(FD->getType()), + getTypeString(FieldType), getStringLiteral(FD->getName())}; if (FD->isBitField()) { @@ -667,15 +669,16 @@ struct BuiltinDumpStructGenerator { ExprResult Field = IFD ? S.BuildAnonymousStructUnionMemberReference( CXXScopeSpec(), Loc, IFD, - DeclAccessPair::make(IFD, AS_public), RecordArg, Loc) + DeclAccessPair::make(IFD, AS_public), RecordArg, nullptr, + Loc) : S.BuildFieldReferenceExpr( - RecordArg, RecordArgIsPtr, Loc, CXXScopeSpec(), FD, - DeclAccessPair::make(FD, AS_public), + RecordArg, RecordArgIsPtr, Loc, NestedNameSpecifierLoc(), + FD, FieldType, DeclAccessPair::make(FD, AS_public), DeclarationNameInfo(FD->getDeclName(), Loc)); if (Field.isInvalid()) return true; - auto *InnerRD = FD->getType()->getAsRecordDecl(); + auto *InnerRD = FieldType->getAsRecordDecl(); auto *InnerCXXRD = dyn_cast_or_null(InnerRD); if (InnerRD && (!InnerCXXRD || InnerCXXRD->isAggregate())) { // Recursively print the values of members of aggregate record type. @@ -684,7 +687,7 @@ struct BuiltinDumpStructGenerator { return true; } else { Format += " "; - if (appendFormatSpecifier(FD->getType(), Format)) { + if (appendFormatSpecifier(FieldType, Format)) { // We know how to print this field. Args.push_back(Field.get()); } else { diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 8dffbca7463dd..fdfef96ee7ba6 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -286,7 +286,7 @@ static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false); if (FromAddr.isInvalid()) return ExprError(); - + // FIXME: resugar return S.BuildCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f28cb137552c0..5659f06e34b30 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13122,6 +13122,7 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, return true; } + // FIXME: Set TypeSourceInfo? VDecl->setType(DeducedType); assert(VDecl->isLinkageValid()); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 88d5c66953b40..0aa51979fe370 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3640,6 +3640,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // We're currently more strict than GCC about what function types we accept. // If this ever proves to be a problem it should be easy to fix. + // FIXME: resugar QualType Ty = S.Context.getPointerType(cast(D)->getType()); QualType ParamTy = FD->getParamDecl(0)->getType(); if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index ed3b867aae1a0..0ed14abf6f8ac 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1554,6 +1554,9 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings, if (FD->isUnnamedBitField()) continue; + // FIXME: Avoid having to recreate the naming context for every field. + QualType FieldType = S.resugar(DecompType.getTypePtr(), FD->getType()); + // We have a real field to bind. assert(FlatBindingsItr != FlatBindings.end()); BindingDecl *B = *(FlatBindingsItr++); @@ -1568,7 +1571,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings, if (E.isInvalid()) return true; E = S.BuildFieldReferenceExpr(E.get(), /*IsArrow*/ false, Loc, - CXXScopeSpec(), FD, + NestedNameSpecifierLoc(), FD, FieldType, DeclAccessPair::make(FD, FD->getAccess()), DeclarationNameInfo(FD->getDeclName(), Loc)); if (E.isInvalid()) @@ -1582,7 +1585,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings, Qualifiers Q = DecompType.getQualifiers(); if (FD->isMutable()) Q.removeConst(); - B->setBinding(S.BuildQualifiedType(FD->getType(), Loc, Q), E.get()); + B->setBinding(S.BuildQualifiedType(FieldType, Loc, Q), E.get()); } return false; @@ -8606,10 +8609,13 @@ class DefaultedComparisonSynthesizer DeclAccessPair Found = DeclAccessPair::make(Field, Field->getAccess()); DeclarationNameInfo NameInfo(Field->getDeclName(), Loc); + QualType FieldType = Field->getType(); return {S.BuildFieldReferenceExpr(Obj.first.get(), /*IsArrow=*/false, Loc, - CXXScopeSpec(), Field, Found, NameInfo), + NestedNameSpecifierLoc(), Field, + FieldType, Found, NameInfo), S.BuildFieldReferenceExpr(Obj.second.get(), /*IsArrow=*/false, Loc, - CXXScopeSpec(), Field, Found, NameInfo)}; + NestedNameSpecifierLoc(), Field, + FieldType, Found, NameInfo)}; } // FIXME: When expanding a subobject, register a note in the code synthesis diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index dc0215f44137f..0077d8321ac88 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3224,6 +3224,7 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, if (!NeedsADL && R.isSingleResult() && !R.getAsSingle() && !ShouldLookupResultBeMultiVersionOverload(R)) + // FIXME: get ConvertedArgs return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(), R.getRepresentativeDecl(), nullptr, nullptr, AcceptInvalidDecl); @@ -3308,6 +3309,10 @@ ExprResult Sema::BuildDeclarationNameExpr( QualType type = VD->getType(); if (type.isNull()) return ExprError(); + assert(!TemplateArgs || ConvertedArgs); + type = ConvertedArgs + ? resugar(SS.getScopeRep(), VD, ConvertedArgs->asArray(), type) + : resugar(SS.getScopeRep(), type); ExprValueKind valueKind = VK_PRValue; // In 'T ...V;', the type of the declaration 'V' is 'T...', but the type of @@ -19895,10 +19900,30 @@ static void DoMarkVarDeclReferenced( // Re-set the member to trigger a recomputation of the dependence bits // for the expression. - if (auto *DRE = dyn_cast_or_null(E)) + CXXScopeSpec SS; + if (auto *DRE = dyn_cast_or_null(E)) { DRE->setDecl(DRE->getDecl()); - else if (auto *ME = dyn_cast_or_null(E)) + SS.Adopt(DRE->getQualifierLoc()); + assert(DRE->template_arguments().size() == 0 || + DRE->getConvertedArgs() != nullptr); + QualType T = DRE->getConvertedArgs() + ? SemaRef.resugar(SS.getScopeRep(), DRE->getDecl(), + DRE->getConvertedArgs()->asArray(), + DRE->getType()) + : SemaRef.resugar(SS.getScopeRep(), DRE->getType()); + DRE->setType(T); + } else if (auto *ME = dyn_cast_or_null(E)) { ME->setMemberDecl(ME->getMemberDecl()); + SS.Adopt(ME->getQualifierLoc()); + assert(ME->template_arguments().size() == 0 || + ME->getDeduced() != nullptr); + QualType T = + ME->getDeduced() + ? SemaRef.resugar(SS.getScopeRep(), ME->getMemberDecl(), + ME->getDeduced()->asArray(), ME->getType()) + : SemaRef.resugar(SS.getScopeRep(), ME->getType()); + ME->setType(T); + } } else if (FirstInstantiation) { SemaRef.PendingInstantiations .push_back(std::make_pair(Var, PointOfInstantiation)); @@ -21200,6 +21225,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { SS.Adopt(DRE->getQualifierLoc()); TemplateArgumentListInfo TemplateArgs; DRE->copyTemplateArgumentsInto(TemplateArgs); + // FIXME: resugar return BuildDeclRefExpr( FD, FD->getType(), VK_LValue, DRE->getNameInfo(), DRE->hasQualifier() ? &SS : nullptr, DRE->getFoundDecl(), diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index f6da4ec339adf..72ae475548e23 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -836,18 +836,14 @@ ExprResult Sema::BuildMemberReferenceExpr( false, ExtraArgs); } -ExprResult -Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, - SourceLocation loc, - IndirectFieldDecl *indirectField, - DeclAccessPair foundDecl, - Expr *baseObjectExpr, - SourceLocation opLoc) { +ExprResult Sema::BuildAnonymousStructUnionMemberReference( + const CXXScopeSpec &SS, SourceLocation loc, + IndirectFieldDecl *indirectField, DeclAccessPair foundDecl, + Expr *baseObjectExpr, const Type *BaseType, SourceLocation opLoc) { // First, build the expression that refers to the base object. // Case 1: the base of the indirect field is not a field. VarDecl *baseVariable = indirectField->getVarDecl(); - CXXScopeSpec EmptySS; if (baseVariable) { assert(baseVariable->getType()->isRecordType()); @@ -860,6 +856,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, DeclarationNameInfo baseNameInfo(DeclarationName(), loc); + CXXScopeSpec EmptySS; ExprResult result = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable); if (result.isInvalid()) return ExprError(); @@ -877,6 +874,8 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, IndirectFieldDecl::chain_iterator FI = indirectField->chain_begin(), FEnd = indirectField->chain_end(); + NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context); + // Case 2: the base of the indirect field is a field and the user // wrote a member expression. if (!baseVariable) { @@ -887,11 +886,16 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, // Make a nameInfo that properly uses the anonymous name. DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); + // FIXME: Avoid redundant setting of the naming scope with the loop below. + QualType FieldType = + BaseType ? resugar(BaseType, SS.getScopeRep(), field->getType()) + : field->getType(); + // Build the first member access in the chain with full information. - result = - BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(), - SS, field, foundDecl, memberNameInfo) - .get(); + result = BuildFieldReferenceExpr(result, baseObjectIsPointer, + SourceLocation(), NNS, field, FieldType, + foundDecl, memberNameInfo) + .get(); if (!result) return ExprError(); } @@ -907,10 +911,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, DeclAccessPair fakeFoundDecl = DeclAccessPair::make(field, field->getAccess()); + QualType FieldType = + BaseType && FI == FEnd + ? resugar(BaseType, SS.getScopeRep(), field->getType()) + : field->getType(); + result = BuildFieldReferenceExpr(result, /*isarrow*/ false, SourceLocation(), - (FI == FEnd ? SS : EmptySS), field, - fakeFoundDecl, memberNameInfo) + (FI == FEnd ? NNS : NestedNameSpecifierLoc()), + field, FieldType, fakeFoundDecl, memberNameInfo) .get(); } @@ -1154,10 +1163,14 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return ExprError(); if (FieldDecl *FD = dyn_cast(MemberDecl)) { + assert(!TemplateArgs); if (ConvertBaseExprToGLValue()) return ExprError(); - return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl, - MemberNameInfo); + NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context); + QualType FieldType = + resugar(BaseType.getTypePtr(), SS.getScopeRep(), FD->getType()); + return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, NNS, FD, FieldType, + FoundDecl, MemberNameInfo); } if (MSPropertyDecl *PD = dyn_cast(MemberDecl)) { @@ -1166,6 +1179,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // Note that this is slightly different behaviour from MSVC which doesn't // implement CWG2813 yet: MSVC might materialize an extra temporary if the // getter or setter function is an explicit object member function. + // FIXME: resugar these. return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD, MemberNameInfo); } @@ -1175,23 +1189,28 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return ExprError(); // We may have found a field within an anonymous union or struct // (C++ [class.union]). - return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, - FoundDecl, BaseExpr, - OpLoc); + return BuildAnonymousStructUnionMemberReference( + SS, MemberLoc, FD, FoundDecl, BaseExpr, BaseType.getTypePtr(), OpLoc); } // Static data member if (VarDecl *Var = dyn_cast(MemberDecl)) { + assert(!TemplateArgs); if (ConvertBaseExprToDiscardedValue()) return ExprError(); - return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, - SS.getWithLocInContext(Context), TemplateKWLoc, Var, + NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context); + QualType VarType = + resugar(BaseType.getTypePtr(), SS.getScopeRep(), Var->getType()); + return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, NNS, TemplateKWLoc, Var, FoundDecl, /*HadMultipleCandidates=*/false, - MemberNameInfo, Var->getType().getNonReferenceType(), + MemberNameInfo, VarType.getNonReferenceType(), VK_LValue, OK_Ordinary); } if (CXXMethodDecl *MemberFn = dyn_cast(MemberDecl)) { + assert(!TemplateArgs); + NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context); + ExprValueKind valueKind; QualType type; if (MemberFn->isInstance()) { @@ -1205,23 +1224,27 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (ConvertBaseExprToDiscardedValue()) return ExprError(); valueKind = VK_LValue; - type = MemberFn->getType(); + type = + resugar(BaseType.getTypePtr(), SS.getScopeRep(), MemberFn->getType()); } - return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, - SS.getWithLocInContext(Context), TemplateKWLoc, + return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, NNS, TemplateKWLoc, MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, type, valueKind, OK_Ordinary); } assert(!isa(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { + assert(!TemplateArgs); if (ConvertBaseExprToDiscardedValue()) return ExprError(); - return BuildMemberExpr( - BaseExpr, IsArrow, OpLoc, SS.getWithLocInContext(Context), - TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandidates=*/false, - MemberNameInfo, Enum->getType(), VK_PRValue, OK_Ordinary); + NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context); + // FIXME: EnumType resugaring not implemented. + QualType EnumType = + resugar(BaseType.getTypePtr(), SS.getScopeRep(), Enum->getType()); + return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, NNS, TemplateKWLoc, Enum, + FoundDecl, /*HadMultipleCandidates=*/false, + MemberNameInfo, EnumType, VK_PRValue, OK_Ordinary); } if (VarTemplateDecl *VarTempl = dyn_cast(MemberDecl)) { @@ -1250,10 +1273,12 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (!Var->getTemplateSpecializationKind()) Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc); - return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, - SS.getWithLocInContext(Context), TemplateKWLoc, Var, + NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context); + QualType VarType = resugar(BaseType.getTypePtr(), SS.getScopeRep(), Var, + ConvertedArgs->asArray(), Var->getType()); + return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, NNS, TemplateKWLoc, Var, FoundDecl, /*HadMultipleCandidates=*/false, - MemberNameInfo, Var->getType().getNonReferenceType(), + MemberNameInfo, VarType.getNonReferenceType(), VK_LValue, OK_Ordinary, TemplateArgs, ConvertedArgs); } @@ -1866,11 +1891,10 @@ void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) { } } -ExprResult -Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, - SourceLocation OpLoc, const CXXScopeSpec &SS, - FieldDecl *Field, DeclAccessPair FoundDecl, - const DeclarationNameInfo &MemberNameInfo) { +ExprResult Sema::BuildFieldReferenceExpr( + Expr *BaseExpr, bool IsArrow, SourceLocation OpLoc, + const NestedNameSpecifierLoc &NNS, FieldDecl *Field, QualType FieldType, + DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo) { // x.a is an l-value if 'a' has a reference type. Otherwise: // x.a is an l-value/x-value/pr-value if the base is (and note // that *x is always an l-value), except that if the base isn't @@ -1887,9 +1911,8 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, OK = OK_BitField; // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] - QualType MemberType = Field->getType(); - if (const ReferenceType *Ref = MemberType->getAs()) { - MemberType = Ref->getPointeeType(); + if (const ReferenceType *Ref = FieldType->getAs()) { + FieldType = Ref->getPointeeType(); VK = VK_LValue; } else { QualType BaseType = BaseExpr->getType(); @@ -1904,22 +1927,21 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, // except that 'mutable' members don't pick up 'const'. if (Field->isMutable()) BaseQuals.removeConst(); - Qualifiers MemberQuals = - Context.getCanonicalType(MemberType).getQualifiers(); + Qualifiers FieldQuals = Context.getCanonicalType(FieldType).getQualifiers(); - assert(!MemberQuals.hasAddressSpace()); + assert(!FieldQuals.hasAddressSpace()); - Qualifiers Combined = BaseQuals + MemberQuals; - if (Combined != MemberQuals) - MemberType = Context.getQualifiedType(MemberType, Combined); + Qualifiers Combined = BaseQuals + FieldQuals; + if (Combined != FieldQuals) + FieldType = Context.getQualifiedType(FieldType, Combined); // Pick up NoDeref from the base in case we end up using AddrOf on the // result. E.g. the expression // &someNoDerefPtr->pointerMember // should be a noderef pointer again. if (BaseType->hasAttr(attr::NoDeref)) - MemberType = - Context.getAttributedType(attr::NoDeref, MemberType, MemberType); + FieldType = + Context.getAttributedType(attr::NoDeref, FieldType, FieldType); } auto isDefaultedSpecialMember = [this](const DeclContext *Ctx) { @@ -1934,8 +1956,8 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, if (!isDefaultedSpecialMember(CurContext)) UnusedPrivateFields.remove(Field); - ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), - FoundDecl, Field); + ExprResult Base = PerformObjectMemberConversion( + BaseExpr, NNS.getNestedNameSpecifier(), FoundDecl, Field); if (Base.isInvalid()) return ExprError(); @@ -1950,10 +1972,10 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, } } - return BuildMemberExpr( - Base.get(), IsArrow, OpLoc, SS.getWithLocInContext(Context), - /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, - /*HadMultipleCandidates=*/false, MemberNameInfo, MemberType, VK, OK); + return BuildMemberExpr(Base.get(), IsArrow, OpLoc, NNS, + /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, + /*HadMultipleCandidates=*/false, MemberNameInfo, + FieldType, VK, OK); } ExprResult diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index fe600386e6fa9..63c486d64f628 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -3339,7 +3339,8 @@ static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E, DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess()); DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc()); ExprResult Res = S.BuildFieldReferenceExpr( - E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo); + E, false, E->getBeginLoc(), NestedNameSpecifierLoc(), FD, + FD->getType(), Found, NameInfo); if (Res.isInvalid()) return false; if (!BuildInitializerList(S, Ctx, Res.get(), List, DestTypes)) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 370e7ca1d918c..78092638a543a 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -10262,12 +10262,13 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( MarkFunctionReferenced(Kind.getLocation(), Best->Function); break; } + QualType RT = Best->Function->getReturnType(); + // FIXME: resugar here // C++ [dcl.type.class.deduct]p1: // The placeholder is replaced by the return type of the function selected // by overload resolution for class template deduction. - QualType DeducedType = - SubstAutoType(TSInfo->getType(), Best->Function->getReturnType()); + QualType DeducedType = SubstAutoType(TSInfo->getType(), RT); Diag(TSInfo->getTypeLoc().getBeginLoc(), diag::warn_cxx14_compat_class_template_argument_deduction) << TSInfo->getTypeLoc().getSourceRange() << 1 << DeducedType; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 0e6191f406866..8f89e159cc964 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2219,6 +2219,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // We were able to resolve the address of the overloaded function, // so we can convert to the type of that function. FromType = Fn->getType(); + // FIXME: resugar SCS.setFromType(FromType); // we can sometimes resolve &foo regardless of ToType, so check @@ -5221,6 +5222,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, const TemplateArgumentList *ConvertedArgs; if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction( Init, DeclType, false, Found, ConvertedArgs)) + // FIXME: resugar T2 = Fn->getType(); } @@ -5712,6 +5714,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, const TemplateArgumentList *ConvertedArgs; if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction( Init, ToType, false, Found, ConvertedArgs)) + // FIXME: resugar T2 = Fn->getType(); } @@ -13610,6 +13613,7 @@ bool Sema::resolveAndFixAddressOfSingleOverloadCandidate( FixOverloadedFunctionReference(E, DAP, Found, /*ConvertedArgs=*/{}); if (Res.isInvalid()) return false; + // FIXME: resugar Expr *Fixed = Res.get(); if (DoFunctionPointerConversion && Fixed->getType()->isFunctionType()) SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false); @@ -15790,13 +15794,28 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, MemExpr = cast(MemExprE->IgnoreParens()); } + assert(Method && "Member call to something that isn't a method?"); - QualType ResultType = Method->getReturnType(); - ExprValueKind VK = Expr::getValueKindForType(ResultType); - ResultType = ResultType.getNonLValueExprType(Context); + QualType MethodType; + { + QualType BaseType = MemExpr->getBase()->getType(); + if (MemExpr->isArrow()) + BaseType = BaseType->castAs()->getPointeeType(); + NestedNameSpecifierLoc NNS = MemExpr->getQualifierLoc(); + // FIXME: Should we resugar the explicit template arguments as well? + const TemplateArgumentList *Deduced = MemExpr->getDeduced(); + MethodType = + Deduced ? resugar(BaseType.getTypePtr(), NNS.getNestedNameSpecifier(), + Method, Deduced->asArray(), Method->getType()) + : resugar(BaseType.getTypePtr(), NNS.getNestedNameSpecifier(), + Method->getType()); + } - assert(Method && "Member call to something that isn't a method?"); - const auto *Proto = Method->getType()->castAs(); + const auto *Proto = MethodType->castAs(); + QualType ReturnType = Proto->getReturnType(); + + ExprValueKind VK = Expr::getValueKindForType(ReturnType); + QualType ResultType = ReturnType.getNonLValueExprType(Context); CallExpr *TheCall = nullptr; llvm::SmallVector NewArgs; @@ -15828,8 +15847,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } // Check for a valid return type. - if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(), - TheCall, Method)) + if (CheckCallReturnType(ReturnType, MemExpr->getMemberLoc(), TheCall, Method)) return BuildRecoveryExpr(ResultType); // Convert the rest of the arguments @@ -16524,9 +16542,18 @@ Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, // We have taken the address of a pointer to member // function. Perform the computation here so that we get the // appropriate pointer to member type. - QualType MemPtrType = Context.getMemberPointerType( - Fn->getType(), Qualifier, - cast(Method->getDeclContext())); + // FIXME: get sugared class type + auto *Cls = cast(Method->getDeclContext()); + if (auto *RD = Qualifier->getAsRecordDecl(); + Cls != RD && Cls->getCanonicalDecl() != RD->getCanonicalDecl()) + // FIXME: Get type as written for the base class. + Qualifier = nullptr; + QualType Type = + Deduced ? resugar(Qualifier, Fn, Deduced->asArray(), Fn->getType()) + : resugar(Qualifier, Fn->getType()); + QualType MemPtrType = + Context.getMemberPointerType(Type, Qualifier, Cls); + // Under the MS ABI, lock down the inheritance model now. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) (void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType); @@ -16555,24 +16582,30 @@ Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, ULE->copyTemplateArgumentsInto(TemplateArgsBuffer); TemplateArgs = &TemplateArgsBuffer; } + NestedNameSpecifierLoc NNS = ULE->getQualifierLoc(); - QualType Type = Fn->getType(); ExprValueKind ValueKind = getLangOpts().CPlusPlus && !Fn->hasCXXExplicitFunctionObjectParameter() ? VK_LValue : VK_PRValue; // FIXME: Duplicated from BuildDeclarationNameExpr. - if (unsigned BID = Fn->getBuiltinID()) { - if (!Context.BuiltinInfo.isDirectlyAddressable(BID)) { + QualType Type; + { + unsigned BID = Fn->getBuiltinID(); + if (BID && !Context.BuiltinInfo.isDirectlyAddressable(BID)) { Type = Context.BuiltinFnTy; ValueKind = VK_PRValue; + } else { + Type = Deduced ? resugar(NNS.getNestedNameSpecifier(), Fn, + Deduced->asArray(), Fn->getType()) + : resugar(NNS.getNestedNameSpecifier(), Fn->getType()); } } DeclRefExpr *DRE = BuildDeclRefExpr( - Fn, Type, ValueKind, ULE->getNameInfo(), ULE->getQualifierLoc(), - Found.getDecl(), ULE->getTemplateKeywordLoc(), TemplateArgs, Deduced); + Fn, Type, ValueKind, ULE->getNameInfo(), NNS, Found.getDecl(), + ULE->getTemplateKeywordLoc(), TemplateArgs, Deduced); DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1); return DRE; } @@ -16584,6 +16617,10 @@ Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer); TemplateArgs = &TemplateArgsBuffer; } + QualType BaseType = MemExpr->getBaseType(); + const Type *BasePointeeType = BaseType->getPointeeType().getTypePtrOrNull(); + if (!BasePointeeType) + BasePointeeType = BaseType.getTypePtr(); Expr *Base; @@ -16591,8 +16628,11 @@ Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, // implicit member access, rewrite to a simple decl ref. if (MemExpr->isImplicitAccess()) { if (cast(Fn)->isStatic()) { + QualType Type = Deduced ? resugar(BasePointeeType, Fn, + Deduced->asArray(), Fn->getType()) + : resugar(BasePointeeType, Fn->getType()); DeclRefExpr *DRE = BuildDeclRefExpr( - Fn, Fn->getType(), VK_LValue, MemExpr->getNameInfo(), + Fn, Type, VK_LValue, MemExpr->getNameInfo(), MemExpr->getQualifierLoc(), Found.getDecl(), MemExpr->getTemplateKeywordLoc(), TemplateArgs, Deduced); DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1); @@ -16601,27 +16641,28 @@ Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, SourceLocation Loc = MemExpr->getMemberLoc(); if (MemExpr->getQualifier()) Loc = MemExpr->getQualifierLoc().getBeginLoc(); - Base = - BuildCXXThisExpr(Loc, MemExpr->getBaseType(), /*IsImplicit=*/true); + Base = BuildCXXThisExpr(Loc, BaseType, /*IsImplicit=*/true); } } else Base = MemExpr->getBase(); ExprValueKind valueKind; - QualType type; + QualType Type; if (cast(Fn)->isStatic()) { valueKind = VK_LValue; - type = Fn->getType(); + Type = Deduced ? resugar(BasePointeeType, Fn, Deduced->asArray(), + Fn->getType()) + : resugar(BasePointeeType, Fn->getType()); } else { valueKind = VK_PRValue; - type = Context.BoundMemberTy; + Type = Context.BoundMemberTy; } return BuildMemberExpr( Base, MemExpr->isArrow(), MemExpr->getOperatorLoc(), MemExpr->getQualifierLoc(), MemExpr->getTemplateKeywordLoc(), Fn, Found, - /*HadMultipleCandidates=*/true, MemExpr->getMemberNameInfo(), - type, valueKind, OK_Ordinary, TemplateArgs); + /*HadMultipleCandidates=*/true, MemExpr->getMemberNameInfo(), Type, + valueKind, OK_Ordinary, TemplateArgs, Deduced); } llvm_unreachable("Invalid reference to overloaded function"); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 479fcc1f147a2..bb3eecbf60bb3 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -152,6 +152,40 @@ class NameMap { insert(CTSD, Info.takeSugared()->asArray()); } + void insert(Sema &SemaRef, const NamedDecl *ND, + ArrayRef Args) { + assert(ND != nullptr); + ND = cast(ND->getCanonicalDecl()); + assert(Args.size() != 0); + switch (ND->getKind()) { + case Decl::Kind::CXXConversion: + case Decl::Kind::CXXMethod: + case Decl::Kind::Function: { + const auto *FD = cast(ND); + assert(FD->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization); + return insert(FD->getPrimaryTemplate(), Args); + } + case Decl::Kind::VarTemplateSpecialization: { + auto STP = cast(ND) + ->getSpecializedTemplateOrPartial(); + auto *VTPSD = STP.dyn_cast(); + if (!VTPSD) + return insert(cast(STP), Args); + + TemplateDeductionInfo Info(SourceLocation{}, + VTPSD->getTemplateParameters()->getDepth()); + [[maybe_unused]] TemplateDeductionResult Res = + SemaRef.DeduceTemplateArguments(VTPSD, Args, Info); + assert(Res == TemplateDeductionResult::Success); + return insert(VTPSD, Info.takeSugared()->asArray()); + } + default: + ND->dumpColor(); + llvm_unreachable("Unhandled Template Kind"); + } + } + void insert(Sema &SemaRef, const NestedNameSpecifier *NNS) { for (/**/; NNS; NNS = NNS->getPrefix()) { switch (NNS->getKind()) { @@ -826,6 +860,82 @@ QualType Sema::resugar(const NestedNameSpecifier *NNS, QualType T) { return Resugarer(*this, Names).transform(T, Changed); } +QualType Sema::resugar(const NestedNameSpecifier *NNS, NamedDecl *ND, + ArrayRef Args, QualType T) { + NameMap Names; + Names.insert(*this, ND, Args); + Names.insert(*this, NNS); + + bool Changed = false; + return Resugarer(*this, Names).transform(T, Changed); +} + +QualType Sema::resugar(NamedDecl *ND, ArrayRef Args, + QualType T) { + NameMap Names; + Names.insert(*this, ND, Args); + + bool Changed = false; + return Resugarer(*this, Names).transform(T, Changed); +} + +static const NestedNameSpecifier *decomposeBaseType(const Type *&Base) { + if (const auto *ElTy = Base->getAs()) { + Base = ElTy->getNamedType().getTypePtr(); + return ElTy->getQualifier(); + } + return nullptr; +} + +QualType Sema::resugar(const Type *Base, QualType T) { + NameMap Names; + const NestedNameSpecifier *BaseNNS = decomposeBaseType(Base); + Names.insert(*this, Base); + Names.insert(*this, BaseNNS); + if (Names.empty()) + return T; + + bool Changed = false; + return Resugarer(*this, Names).transform(T, Changed); +} +QualType Sema::resugar(const Type *Base, NamedDecl *ND, + ArrayRef Args, QualType T) { + NameMap Names; + Names.insert(*this, ND, Args); + const NestedNameSpecifier *BaseNNS = decomposeBaseType(Base); + Names.insert(*this, Base); + Names.insert(*this, BaseNNS); + + bool Changed = false; + return Resugarer(*this, Names).transform(T, Changed); +} +QualType Sema::resugar(const Type *Base, const NestedNameSpecifier *FieldNNS, + QualType T) { + NameMap Names; + Names.insert(*this, FieldNNS); + const NestedNameSpecifier *BaseNNS = decomposeBaseType(Base); + Names.insert(*this, Base); + Names.insert(*this, BaseNNS); + if (Names.empty()) + return T; + + bool Changed = false; + return Resugarer(*this, Names).transform(T, Changed); +} +QualType Sema::resugar(const Type *Base, const NestedNameSpecifier *FieldNNS, + NamedDecl *ND, ArrayRef Args, + QualType T) { + NameMap Names; + Names.insert(*this, ND, Args); + Names.insert(*this, FieldNNS); + const NestedNameSpecifier *BaseNNS = decomposeBaseType(Base); + Names.insert(*this, Base); + Names.insert(*this, BaseNNS); + + bool Changed = false; + return Resugarer(*this, Names).transform(T, Changed); +} + /// \brief Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, /// returns null. diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 5b79226a8be42..83fdc73965915 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4205,6 +4205,10 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R, S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false)) return {}; + // FIXME: get SS. + QualType FT = + Args.size() != 0 ? S.resugar(Fn, Args, Fn->getType()) : Fn->getType(); + if (CXXMethodDecl *Method = dyn_cast(Fn)) if (Method->isImplicitObjectMemberFunction()) { // An instance method that's referenced in a form that doesn't @@ -4212,12 +4216,14 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R, if (!R.HasFormOfMemberPointer) return {}; - return S.Context.getMemberPointerType( - Fn->getType(), /*Qualifier=*/nullptr, Method->getParent()); + // FIXME: resugar the class type here. + return S.Context.getMemberPointerType(FT, /*Qualifier=*/nullptr, + Method->getParent()); } - if (!R.IsAddressOfOperand) return Fn->getType(); - return S.Context.getPointerType(Fn->getType()); + if (!R.IsAddressOfOperand) + return FT; + return S.Context.getPointerType(FT); } /// Apply the deduction rules for overload sets. @@ -4334,6 +4340,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, // treated as a non-deduced context. [...] if (!Match.isNull() && !S.isSameOrCompatibleFunctionType(Match, ArgType)) return {}; + // FIXME: resugar Match = ArgType; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 222dd932aab37..ead3784b061a0 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2921,8 +2921,10 @@ class TreeTransform { } CXXScopeSpec EmptySS; + // FIXME: resugar. return getSema().BuildFieldReferenceExpr( - Base, isArrow, OpLoc, EmptySS, cast(Member), + Base, isArrow, OpLoc, NestedNameSpecifierLoc(), + cast(Member), Member->getType(), DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()), MemberNameInfo); } diff --git a/clang/test/AST/ast-dump-for-range-lifetime.cpp b/clang/test/AST/ast-dump-for-range-lifetime.cpp index ee046be19ab63..db1a8335cd89e 100644 --- a/clang/test/AST/ast-dump-for-range-lifetime.cpp +++ b/clang/test/AST/ast-dump-for-range-lifetime.cpp @@ -135,7 +135,7 @@ void test4() { // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()' - for (auto e : default_arg_fn()) + for (auto e : default_arg_fn()) bar(e); } @@ -293,17 +293,17 @@ void test8() { // CHECK: -CXXForRangeStmt {{.*}} // CHECK-NEXT: |-<<>> // CHECK-NEXT: |-DeclStmt {{.*}} - // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'const P2718R0::A &' cinit - // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'const P2718R0::A' lvalue - // CHECK-NEXT: | `-CallExpr {{.*}} 'const P2718R0::A' lvalue - // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'const P2718R0::A &(*)(const P2718R0::A &)' - // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const P2718R0::A &(const P2718R0::A &)' lvalue Function {{.*}} 'df1' 'const P2718R0::A &(const P2718R0::A &)' (FunctionTemplate {{.*}} 'df1') - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'const P2718R0::A &' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const P2718R0::A' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CallExpr {{.*}} 'P2718R0::A' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'P2718R0::A (*)()' - // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'P2718R0::A ()' lvalue Function {{.*}} 'dg' 'P2718R0::A ()' (FunctionTemplate {{.*}} 'dg') + // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'A const &' cinit + // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'A const':'const P2718R0::A' lvalue + // CHECK-NEXT: | `-CallExpr {{.*}} 'A const':'const P2718R0::A' lvalue + // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'A const &(*)(A const &)' + // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'A const &(A const &)' lvalue Function {{.*}} 'df1' 'const P2718R0::A &(const P2718R0::A &)' (FunctionTemplate {{.*}} 'df1') + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'A const &' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'A (*)()' + // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'A ()' lvalue Function {{.*}} 'dg' 'P2718R0::A ()' (FunctionTemplate {{.*}} 'dg') for (auto e : df1(dg())) sum += e; } @@ -319,8 +319,8 @@ void test9() { // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'int (&)[3]' cinit // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue // CHECK-NEXT: | `-CallExpr {{.*}} 'int[3]' lvalue - // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'int (&(*)(const P2718R0::A *))[3]' - // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const P2718R0::A *))[3]' lvalue Function {{.*}} 'df2' 'int (&(const P2718R0::A *))[3]' (FunctionTemplate {{.*}} 'df2') + // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'int (&(*)(const A *))[3]' + // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A *))[3]' lvalue Function {{.*}} 'df2' 'int (&(const P2718R0::A *))[3]' (FunctionTemplate {{.*}} 'df2') // CHECK-NEXT: | `-CallExpr {{.*}} 'const A *' // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'const A *(*)(const A &)' // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const A *(const A &)' lvalue Function {{.*}} 'dg2' 'const A *(const A &)' @@ -345,9 +345,9 @@ void test10() { // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue // CHECK-NEXT: | `-BinaryOperator {{.*}} 'int[3]' lvalue ',' // CHECK-NEXT: | |-CXXStaticCastExpr {{.*}} 'void' static_cast - // CHECK-NEXT: | | `-CallExpr {{.*}} 'const P2718R0::LockGuard' lvalue - // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const P2718R0::LockGuard &(*)(const P2718R0::LockGuard &)' - // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') + // CHECK-NEXT: | | `-CallExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue + // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const LockGuard &(*)(const LockGuard &)' + // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const LockGuard &(const LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) @@ -363,9 +363,9 @@ void test10() { // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue // CHECK-NEXT: | `-BinaryOperator {{.*}} 'int[3]' lvalue ',' // CHECK-NEXT: | |-CStyleCastExpr {{.*}} 'void' - // CHECK-NEXT: | | `-CallExpr {{.*}} 'const P2718R0::LockGuard' lvalue - // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const P2718R0::LockGuard &(*)(const P2718R0::LockGuard &)' - // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') + // CHECK-NEXT: | | `-CallExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue + // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const LockGuard &(*)(const LockGuard &)' + // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const LockGuard &(const LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) @@ -380,17 +380,17 @@ void test10() { // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'int (&)[3]' cinit // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue // CHECK-NEXT: | `-BinaryOperator {{.*}} 'int[3]' lvalue ',' - // CHECK-NEXT: | |-BinaryOperator {{.*}} 'const P2718R0::LockGuard' lvalue ',' - // CHECK-NEXT: | | |-CallExpr {{.*}} 'const P2718R0::LockGuard' lvalue - // CHECK-NEXT: | | | |-ImplicitCastExpr {{.*}} 'const P2718R0::LockGuard &(*)(const P2718R0::LockGuard &)' - // CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') + // CHECK-NEXT: | |-BinaryOperator {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue ',' + // CHECK-NEXT: | | |-CallExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue + // CHECK-NEXT: | | | |-ImplicitCastExpr {{.*}} 'const LockGuard &(*)(const LockGuard &)' + // CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} 'const LockGuard &(const LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' 'void ()' - // CHECK-NEXT: | | `-CallExpr {{.*}} 'const P2718R0::LockGuard' lvalue - // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const P2718R0::LockGuard &(*)(const P2718R0::LockGuard &)' - // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') + // CHECK-NEXT: | | `-CallExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue + // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const LockGuard &(*)(const LockGuard &)' + // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const LockGuard &(const LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) @@ -403,7 +403,7 @@ void test10() { // Test default argument && dependent context template int (&default_arg_fn2(const T & = T()))[3]; void test11() { - for (auto e : default_arg_fn2()) + for (auto e : default_arg_fn2()) bar(e); } @@ -441,11 +441,11 @@ void test13() { // CHECK-NEXT: | `-MemberExpr {{.*}} '' .g {{.*}} // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' lvalue // CHECK-NEXT: | `-MemberExpr {{.*}} '' .r {{.*}} - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CallExpr {{.*}} 'P2718R0::A' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'P2718R0::A (*)()' - // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'P2718R0::A ()' lvalue Function {{.*}} 'dg' 'P2718R0::A ()' (FunctionTemplate {{.*}} 'dg') + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A':'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'A (*)()' + // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'A ()' lvalue Function {{.*}} 'dg' 'P2718R0::A ()' (FunctionTemplate {{.*}} 'dg') for (auto e : dg().r().g().r().g().r().g()) bar(e); } diff --git a/clang/test/Analysis/cast-value-notes.cpp b/clang/test/Analysis/cast-value-notes.cpp index acd33e704d13a..af6871b448276 100644 --- a/clang/test/Analysis/cast-value-notes.cpp +++ b/clang/test/Analysis/cast-value-notes.cpp @@ -73,7 +73,7 @@ void clang_analyzer_printState(); #if defined(X86) void evalReferences(const Shape &S) { const auto &C = dyn_cast(S); - // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle &'}} + // expected-note@-1 {{Assuming 'S' is not a 'const Circle &'}} // expected-note@-2 {{Dereference of null pointer}} // expected-warning@-3 {{Dereference of null pointer}} clang_analyzer_printState(); @@ -86,26 +86,26 @@ void evalReferences_addrspace(const Shape &S) { const auto &C = dyn_cast(S); clang_analyzer_printState(); // X86-CHECK-SUPPRESSED: "dynamic_types": [ - // X86-CHECK-SUPPRESSED-NEXT: { "region": "SymRegion{reg_$0}", "dyn_type": "const __attribute__((address_space(3))) class clang::Circle &", "sub_classable": true } + // X86-CHECK-SUPPRESSED-NEXT: { "region": "SymRegion{reg_$0}", "dyn_type": "DEVICE Circle const &", "sub_classable": true } (void)C; } #endif #if defined(NOT_SUPPRESSED) void evalReferences_addrspace(const Shape &S) { const auto &C = dyn_cast(S); - // expected-note@-1 {{Assuming 'S' is not a 'const __attribute__((address_space(3))) class clang::Circle &'}} + // expected-note@-1 {{Assuming 'S' is not a 'DEVICE Circle const &'}} // expected-note@-2 {{Dereference of null pointer}} // expected-warning@-3 {{Dereference of null pointer}} clang_analyzer_printState(); // X86-CHECK: "dynamic_types": [ - // X86-CHECK-NEXT: { "region": "SymRegion{reg_$0}", "dyn_type": "const __attribute__((address_space(3))) class clang::Circle &", "sub_classable": true } + // X86-CHECK-NEXT: { "region": "SymRegion{reg_$0}", "dyn_type": "DEVICE Circle const &", "sub_classable": true } (void)C; } #endif #elif defined(MIPS) void evalReferences(const Shape &S) { const auto &C = dyn_cast(S); - // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle &'}} + // expected-note@-1 {{Assuming 'S' is not a 'const Circle &'}} // expected-note@-2 {{Dereference of null pointer}} // expected-warning@-3 {{Dereference of null pointer}} } @@ -122,25 +122,25 @@ void evalNonNullParamNonNullReturnReference(const Shape &S) { // expected-note@-1 {{'C' initialized here}} if (!dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is a 'const class clang::Circle *'}} + // expected-note@-1 {{Assuming 'C' is a 'const Circle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Triangle *'}} + // expected-note@-1 {{Assuming 'C' is not a 'const Triangle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Rectangle *'}} + // expected-note@-1 {{Assuming 'C' is not a 'const Rectangle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Hexagon *'}} + // expected-note@-1 {{Assuming 'C' is not a 'const Hexagon *'}} // expected-note@-2 {{Taking false branch}} return; } @@ -176,29 +176,29 @@ void evalNonNullParamNonNullReturnReference(const Shape &S) { void evalNonNullParamNonNullReturn(const Shape *S) { const auto *C = cast(S); - // expected-note@-1 {{'S' is a 'const class clang::Circle *'}} + // expected-note@-1 {{'S' is a 'const Circle *'}} // expected-note@-2 {{'C' initialized here}} if (!dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is a 'const class clang::Circle *'}} + // expected-note@-1 {{Assuming 'C' is a 'const Circle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Triangle *'}} + // expected-note@-1 {{Assuming 'C' is not a 'const Triangle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Rectangle *'}} + // expected-note@-1 {{Assuming 'C' is not a 'const Rectangle *'}} // expected-note@-2 {{Taking false branch}} return; } if (dyn_cast_or_null(C)) { - // expected-note@-1 {{Assuming 'C' is not a 'const class clang::Hexagon *'}} + // expected-note@-1 {{Assuming 'C' is not a 'const Hexagon *'}} // expected-note@-2 {{Taking false branch}} return; } @@ -234,10 +234,10 @@ void evalNonNullParamNonNullReturn(const Shape *S) { void evalNonNullParamNullReturn(const Shape *S) { const auto *C = dyn_cast_or_null(S); - // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle *'}} + // expected-note@-1 {{Assuming 'S' is not a 'const Circle *'}} if (const auto *T = dyn_cast_or_null(S)) { - // expected-note@-1 {{Assuming 'S' is a 'const class clang::Triangle *'}} + // expected-note@-1 {{Assuming 'S' is a 'const Triangle *'}} // expected-note@-2 {{'T' initialized here}} // expected-note@-3 {{'T' is non-null}} // expected-note@-4 {{Taking true branch}} @@ -261,7 +261,7 @@ void evalNullParamNullReturn(const Shape *S) { void evalZeroParamNonNullReturnPointer(const Shape *S) { const auto *C = S->castAs(); - // expected-note@-1 {{'S' is a 'const class clang::Circle *'}} + // expected-note@-1 {{'S' is a 'const Circle *'}} // expected-note@-2 {{'C' initialized here}} (void)(1 / !C); @@ -282,12 +282,12 @@ void evalZeroParamNonNullReturn(const Shape &S) { void evalZeroParamNullReturn(const Shape *S) { const auto &C = S->getAs(); - // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle *'}} + // expected-note@-1 {{Assuming 'S' is not a 'const Circle *'}} // expected-note@-2 {{Storing null pointer value}} // expected-note@-3 {{'C' initialized here}} if (!dyn_cast_or_null(S)) { - // expected-note@-1 {{Assuming 'S' is a 'const class clang::Triangle *'}} + // expected-note@-1 {{Assuming 'S' is a 'const Triangle *'}} // expected-note@-2 {{Taking false branch}} return; } diff --git a/clang/test/Analysis/cast-value-state-dump.cpp b/clang/test/Analysis/cast-value-state-dump.cpp index 07fd7abd848ab..ee2854759fcc2 100644 --- a/clang/test/Analysis/cast-value-state-dump.cpp +++ b/clang/test/Analysis/cast-value-state-dump.cpp @@ -18,12 +18,12 @@ using namespace clang; void evalNonNullParamNonNullReturn(const Shape *S) { const auto *C = dyn_cast_or_null(S); - // expected-note@-1 {{Assuming 'S' is a 'const class clang::Circle *'}} + // expected-note@-1 {{Assuming 'S' is a 'const Circle *'}} // expected-note@-2 {{'C' initialized here}} // FIXME: We assumed that 'S' is a 'Circle' therefore it is not a 'Square'. if (dyn_cast_or_null(S)) { - // expected-note@-1 {{Assuming 'S' is not a 'const class clang::Square *'}} + // expected-note@-1 {{Assuming 'S' is not a 'const Square *'}} // expected-note@-2 {{Taking false branch}} return; } @@ -31,7 +31,7 @@ void evalNonNullParamNonNullReturn(const Shape *S) { clang_analyzer_printState(); // CHECK: "dynamic_types": [ - // CHECK-NEXT: { "region": "SymRegion{reg_$0}", "dyn_type": "const class clang::Circle", "sub_classable": true } + // CHECK-NEXT: { "region": "SymRegion{reg_$0}", "dyn_type": "const Circle", "sub_classable": true } // CHECK-NEXT: ], // CHECK-NEXT: "dynamic_casts": [ // CHECK: { "region": "SymRegion{reg_$0}", "casts": [ diff --git a/clang/test/Analysis/lifetime-extended-regions.cpp b/clang/test/Analysis/lifetime-extended-regions.cpp index 4458ad294af7c..59f43a59add16 100644 --- a/clang/test/Analysis/lifetime-extended-regions.cpp +++ b/clang/test/Analysis/lifetime-extended-regions.cpp @@ -54,7 +54,7 @@ void member_access() { int&& x = Composite{}.x; // extends `Composite` clang_analyzer_dump(x); // expected-warning-re {{&lifetime_extended_object{Composite, x, S{{[0-9]+}}}.x }} int&& y = create().y; // extends `Composite` - clang_analyzer_dump(y); // expected-warning-re {{&lifetime_extended_object{struct Composite, y, S{{[0-9]+}}}.y }} + clang_analyzer_dump(y); // expected-warning-re {{&lifetime_extended_object{Composite, y, S{{[0-9]+}}}.y }} int&& d = Array{}.front(); // dangles `Array` clang_analyzer_dump(d); // expected-warning-re {{&Element{temp_object{Array, S{{[0-9]+}}}.array,0 S64b,int} }} } @@ -120,7 +120,7 @@ void aggregateWithReferences() { clang_analyzer_dump(viaReference); // expected-warning-re {{&lifetime_extended_object{RefAggregate, viaReference, S{{[0-9]+}}} }} clang_analyzer_dump(viaReference.rx); // expected-warning-re {{&lifetime_extended_object{int, viaReference, S{{[0-9]+}}} }} clang_analyzer_dump(viaReference.ry); // expected-warning-re {{&lifetime_extended_object{Composite, viaReference, S{{[0-9]+}}} }} - + // FIXME: clang currently support extending lifetime of object bound to reference members of aggregates, // that are created from default member initializer. But CFG and ExprEngine need to be updated to address this change. // The following expect warning: {{&lifetime_extended_object{Composite, defaultInitExtended, S{{[0-9]+}}} }} @@ -140,8 +140,8 @@ void lambda() { // See also CWG2737 (https://cplusplus.github.io/CWG/issues/2737.html) auto const refExtendingCapture = [&refCapture = create()] { clang_analyzer_dump(refCapture); - // cpp14-warning-re@-1 {{&temp_object{const struct Composite, S{{[0-9]+}}} }} - // cpp17-warning-re@-2 {{&lifetime_extended_object{const struct Composite, refExtendingCapture, S{{[0-9]+}}} }} + // cpp14-warning-re@-1 {{&temp_object{const Composite, S{{[0-9]+}}} }} + // cpp17-warning-re@-2 {{&lifetime_extended_object{const Composite, refExtendingCapture, S{{[0-9]+}}} }} }; refExtendingCapture(); } diff --git a/clang/test/CXX/class.derived/class.abstract/p3.cpp b/clang/test/CXX/class.derived/class.abstract/p3.cpp index cf973d2567294..4616ad5c7e6ed 100644 --- a/clang/test/CXX/class.derived/class.abstract/p3.cpp +++ b/clang/test/CXX/class.derived/class.abstract/p3.cpp @@ -75,7 +75,7 @@ void h() { template void t(T); void i(A &a, B &b, C &c, D &d) { t(a); // expected-error {{allocating an object of abstract class type 'A'}} - t(b); // expected-error {{allocating an object of abstract class type 'SecretlyAbstract'}} + t(b); // expected-error {{allocating an object of abstract class type 'B' (aka 'SecretlyAbstract')}} t(c); // expected-error {{allocating an object of abstract class type}} t(d); // ok, decays to pointer } diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp index d144cf9e4e868..2262a11055148 100644 --- a/clang/test/CXX/drs/cwg23xx.cpp +++ b/clang/test/CXX/drs/cwg23xx.cpp @@ -63,7 +63,7 @@ template void foo(T&, ...); struct Q; // #cwg2304-Q void fn1(Q &data_vectors) { foo(data_vectors, 0); - // expected-error@-1 {{argument type 'cwg2304::Q' is incomplete}} + // expected-error@-1 {{argument type 'Q' is incomplete}} // expected-note@#cwg2304-Q {{forward declaration of 'cwg2304::Q'}} } } // namespace cwg2304 @@ -91,7 +91,7 @@ struct Y {}; struct Z : W, X, check_derived_from, // #cwg2310-X check_derived_from, Y // #cwg2310-Y -{ +{ // FIXME: It was properly rejected before, but we're crashing since Clang 11 in C++11 and C++14 modes. // See https://github.com/llvm/llvm-project/issues/59920 #if __cplusplus >= 201703L diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp index 3eb70583b6026..c56bf29b8770f 100644 --- a/clang/test/CXX/drs/cwg26xx.cpp +++ b/clang/test/CXX/drs/cwg26xx.cpp @@ -90,7 +90,7 @@ D d(); std::int32_t d1{ d().i }; std::int32_t d2{ d().i }; std::int32_t d3{ d().i }; -// since-cxx11-error@-1 {{non-constant-expression cannot be narrowed from type 'long long' to 'std::int32_t' (aka 'int') in initializer list}} +// since-cxx11-error@-1 {{non-constant-expression cannot be narrowed from type 'std::int64_t' (aka 'long long') to 'std::int32_t' (aka 'int') in initializer list}} // since-cxx11-note@-2 {{insert an explicit cast to silence this issue}} std::int16_t d6{ d().i }; diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp index e8e2600870233..c9596d8b4e9d8 100644 --- a/clang/test/CXX/drs/cwg4xx.cpp +++ b/clang/test/CXX/drs/cwg4xx.cpp @@ -565,16 +565,16 @@ namespace cwg428 { // cwg428: 2.7 // expected-error@-1 {{cannot throw object of incomplete type 'struct X'}} // expected-note@#cwg428-X {{forward declaration of 'cwg428::X'}} throw make(); - // expected-error@-1 {{cannot throw object of incomplete type 'cwg428::X'}} + // expected-error@-1 {{cannot throw object of incomplete type 'X'}} // expected-note@#cwg428-X {{forward declaration of 'cwg428::X'}} throw make(); - // expected-error@-1 {{cannot throw pointer to object of incomplete type 'cwg428::X'}} + // expected-error@-1 {{cannot throw pointer to object of incomplete type 'X'}} // expected-note@#cwg428-X {{forward declaration of 'cwg428::X'}} throw make(); - // expected-error@-1 {{cannot throw object of incomplete type 'cwg428::X'}} + // expected-error@-1 {{cannot throw object of incomplete type 'X'}} // expected-note@#cwg428-X {{forward declaration of 'cwg428::X'}} throw make(); - // expected-error@-1 {{cannot throw pointer to object of incomplete type 'const volatile cwg428::X'}} + // expected-error@-1 {{cannot throw pointer to object of incomplete type 'const volatile X'}} // expected-note@#cwg428-X {{forward declaration of 'cwg428::X'}} } } // namespace cwg428 diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp index e2eb009508b52..004c02bed7f86 100644 --- a/clang/test/CXX/drs/cwg6xx.cpp +++ b/clang/test/CXX/drs/cwg6xx.cpp @@ -750,7 +750,7 @@ namespace cwg656 { // cwg656: 2.8 void f() { accept(x); accept(y); - // expected-error@-1 {{cannot cast 'const Y' to its private base class 'const cwg656::A'}} + // expected-error@-1 {{cannot cast 'const Y' to its private base class 'const A'}} // expected-note@#cwg656-Y {{declared private here}} accept(vy); // #cwg656-vy // expected-error@-1 {{call to deleted function 'accept'}} diff --git a/clang/test/Misc/diag-template-diffing-cxx11.cpp b/clang/test/Misc/diag-template-diffing-cxx11.cpp index c62bffe2b458d..9f80604bf3f04 100644 --- a/clang/test/Misc/diag-template-diffing-cxx11.cpp +++ b/clang/test/Misc/diag-template-diffing-cxx11.cpp @@ -1169,7 +1169,7 @@ Wrapper> W12 = // CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper>' to 'Wrapper>' Wrapper> W13 = MakeWrapper>(); -// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper>' to 'Wrapper>' +// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper>' to 'Wrapper>' Wrapper> W14 = MakeWrapper>(); // CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper>' to 'Wrapper>' } @@ -1381,8 +1381,8 @@ namespace DefaultNonTypeArgWithDependentType { template struct A {}; template > R bar(); A<> &foo() { return bar(); } -// CHECK-ELIDE-NOTREE: error: non-const lvalue reference to type 'A<...>' cannot bind to a temporary of type 'A<...>' -// CHECK-NOELIDE-NOTREE: error: non-const lvalue reference to type 'A' cannot bind to a temporary of type 'A' +// CHECK-ELIDE-NOTREE: error: non-const lvalue reference to type 'A<>' cannot bind to a temporary of type 'A<>' +// CHECK-NOELIDE-NOTREE: error: non-const lvalue reference to type 'A<>' cannot bind to a temporary of type 'A<>' } namespace PR24587 { diff --git a/clang/test/Sema/Resugar/resugar-expr.cpp b/clang/test/Sema/Resugar/resugar-expr.cpp new file mode 100644 index 0000000000000..336c480b359cc --- /dev/null +++ b/clang/test/Sema/Resugar/resugar-expr.cpp @@ -0,0 +1,227 @@ +// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify %s + +enum class Z; + +struct bar {}; + +using Int = int; +using Float = float; +using Bar = bar; + +namespace t1 { +template struct A { + static constexpr A1 a = {}; +}; + +Z x1 = A::a; +// expected-error@-1 {{with an lvalue of type 'const Int' (aka 'const int')}} +} // namespace t1 + +namespace t2 { +template struct A { + static constexpr A1 A2::*a = {}; +}; + +Z x1 = A::a; +// expected-error@-1 {{with an lvalue of type 'Int Bar::*const'}} +} // namespace t2 + +namespace t3 { +template struct A { + template struct B { + static constexpr A1 B1::*a = {}; + }; +}; + +Z x1 = A::B::a; +// expected-error@-1 {{with an lvalue of type 'Float Bar::*const'}} +} // namespace t3 + +namespace t4 { +template A1 (*a) (); + +// FIXME: resugar this +Z x1 = decltype(a){}(); +// expected-error@-1 {{with an rvalue of type 'int'}} +} // namespace t4 + +namespace t5 { +template struct A { + A1(*a) + (); +}; + +// FIXME: resugar this +Z x1 = decltype(A().a){}(); +// expected-error@-1 {{with an rvalue of type 'int'}} +} // namespace t5 + +namespace t6 { +template struct A { A2 A1::*f(); }; + +using M = int; +using N = int; + +struct B {}; +using X = B; +using Y = B; + +auto a = &A::f; +Z x1 = a; +// expected-error@-1 {{with an lvalue of type 'M X::*(A::*)()'}} + +A b; +Z x2 = (b.*a)(); +// expected-error@-1 {{with an rvalue of type 'M X::*'}} + +Z x3 = decltype((b.*a)()){}; +// expected-error@-1 {{with an rvalue of type 'decltype((b .* a)())' (aka 'M X::*')}} +} // namespace t6 + +namespace t7 { +template struct A { A1 a; }; +auto [a] = A{}; + +Z x1 = a; +// expected-error@-1 {{with an lvalue of type 'Int' (aka 'int')}} +} // namespace t7 + +namespace t8 { +template struct A { + template static constexpr B1 (*b)(A1) = nullptr; +}; + +Z x1 = A::b; +// expected-error@-1 {{with an lvalue of type 'Int (*const)(Float)' (aka 'int (*const)(float)')}} +} // namespace t8 + +namespace t9 { +template struct A { + template static constexpr auto b = (B1(*)(A1)){}; +}; + +Z x1 = A::b; +// expected-error@-1 {{with an lvalue of type 'Int (*const)(Float)' (aka 'int (*const)(float)'}} +} // namespace t9 + +namespace t10 { +template struct A { + template static constexpr A1 (*m)(B1) = nullptr; +}; + +Z x1 = A().template m; +// expected-error@-1 {{with an lvalue of type 'Int (*const)(Float)' (aka 'int (*const)(float)'}} +} // namespace t10 + +namespace t11 { +template A1 a; +template A2 a; + +Z x1 = a; +// expected-error@-1 {{with an lvalue of type 'Int' (aka 'int')}} + +Z x2 = a; +// expected-error@-1 {{with an lvalue of type 'Float' (aka 'float')}} +} // namespace t11 + +namespace t12 { +template A1 *a; +template decltype(a) a; + +// FIXME: resugar this +Z x1 = *a; +// expected-error@-1 {{with an lvalue of type 'int[0]'}} +} // namespace t12 + +namespace t13 { +template struct A { A1 foo(); }; + +Z x1 = A().foo(); +// expected-error@-1 {{with an rvalue of type 'Int' (aka 'int')}} +} // namespace t13 + +namespace t14 { +template struct A { + auto foo() { return A1(); }; +}; + +Z x1 = A().foo(); +// expected-error@-1 {{with an rvalue of type 'Int' (aka 'int')}} +} // namespace t14 + +namespace t15 { +template struct A { + template auto foo1() -> A1 (*)(B1); + template auto foo2(B1) -> A1 (*)(B1); +}; + +Z x1 = A().foo1(); +// expected-error@-1 {{with an rvalue of type 'Int (*)(Float)' (aka 'int (*)(float)'}} + +Z x2 = A().foo2(Float()); +// expected-error@-1 {{with an rvalue of type 'Int (*)(Float)' (aka 'int (*)(float)'}} +} // namespace t15 + +namespace t16 { +template struct A { + static auto foo() -> A1; +}; + +Z x1 = A().foo(); +// expected-error@-1 {{with an rvalue of type 'Int' (aka 'int')}} +} // namespace t16 + +namespace t17 { +template static auto foo() -> A1; + +Z x1 = foo(); +// expected-error@-1 {{with an rvalue of type 'Int' (aka 'int')}} +} // namespace t17 + +namespace t18 { +template static auto foo(A1) -> A1*; + +Z x1 = foo(Int()); +// expected-error@-1 {{with an rvalue of type 'Int *' (aka 'int *')}} +} // namespace t18 + +namespace t19 { +template struct A { + template static auto foo() -> A1 (*)(B1); +}; + +Z x1 = A().template foo(); +// expected-error@-1 {{with an rvalue of type 'Int (*)(Float)' (aka 'int (*)(float)'}} + +Z x2 = A::template foo(); +// expected-error@-1 {{with an rvalue of type 'Int (*)(Float)' (aka 'int (*)(float)'}} +} // namespace t19 + +namespace t20 { +template struct A { + A1 m; +}; + +Z x1 = A().m; +// expected-error@-1 {{with an rvalue of type 'Int' (aka 'int')}} +} // namespace t20 + +namespace t21 { +template struct A { + static A1 m; +}; + +Z x1 = A().m; +// expected-error@-1 {{with an lvalue of type 'Int' (aka 'int')}} +} // namespace t21 + +namespace t22 { +template struct A { + struct { + A1 m; + }; +}; + +Z x1 = A().m; +// expected-error@-1 {{with an rvalue of type 'Int' (aka 'int')}} +} // namespace t22 diff --git a/clang/test/SemaTemplate/attributes.cpp b/clang/test/SemaTemplate/attributes.cpp index dea19d09745ca..10127f17a4532 100644 --- a/clang/test/SemaTemplate/attributes.cpp +++ b/clang/test/SemaTemplate/attributes.cpp @@ -632,7 +632,8 @@ namespace preferred_name { }; template T desugar(T); auto it = desugar(MemberTemplate::Iter()); - int n = it; // expected-error {{no viable conversion from 'preferred_name::MemberTemplate::const_iterator' to 'int'}} + // FIXME: We need to implement a __builtin_canonicalize_type for this ;-) + int n = it; // expected-error {{no viable conversion from 'MemberTemplate::Iter' to 'int'}} template struct Foo; template using Bar = Foo<1, 2, T...>; diff --git a/clang/unittests/Tooling/StencilTest.cpp b/clang/unittests/Tooling/StencilTest.cpp index 445912a53e8b6..1ef15b5ce09bd 100644 --- a/clang/unittests/Tooling/StencilTest.cpp +++ b/clang/unittests/Tooling/StencilTest.cpp @@ -556,8 +556,9 @@ TEST_F(StencilTest, DescribeUnqualifiedType) { } TEST_F(StencilTest, DescribeAnonNamespaceType) { + // FIXME: We need to implement a __builtin_canonicalize_type for this ;-) std::string Snippet = "auto c = desugar(); c;"; - std::string Expected = "(anonymous namespace)::AnonC"; + std::string Expected = "AnonC"; auto StmtMatch = matchStmt(Snippet, declRefExpr(hasType(qualType().bind("type")))); ASSERT_TRUE(StmtMatch);