Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -6161,6 +6161,8 @@ "|%diff{casting $ to type $|casting between types}0,1}2" " discards qualifiers">, InGroup; +def note_nested_pointer_discarded_qualifier : Note< + "nested pointer type with discarded 'const' qualifier">; def ext_nested_pointer_qualifier_mismatch : ExtWarn< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -8352,10 +8352,10 @@ /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the /// assignment conversion type specified by ConvTy. This returns true if the /// conversion was invalid or false if the conversion was accepted. - bool DiagnoseAssignmentResult(AssignConvertType ConvTy, - SourceLocation Loc, - QualType DstType, QualType SrcType, - Expr *SrcExpr, AssignmentAction Action, + bool DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, + QualType DstType, VarDecl *DstVarDecl, + QualType SrcType, Expr *SrcExpr, + AssignmentAction Action, bool *Complained = nullptr); /// IsValueInFlagEnum - Determine if a value is allowed as part of a flag Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -728,7 +728,8 @@ ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); if (RHS.isInvalid()) return true; - if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy, + if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, + /* lhs declaration */ nullptr, RHSTy, RHS.get(), AA_Assigning)) return true; } Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -9612,8 +9612,11 @@ ConvTy = CheckAssignmentConstraints(Loc, LHSType, RHSType); } - if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType, - RHS.get(), AA_Assigning)) + DeclRefExpr *DeclRef = dyn_cast(LHSExpr); + if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, + DeclRef->getDecl() ? DeclRef->getDecl() + : nullptr, + RHSType, RHS.get(), AA_Assigning)) return QualType(); CheckForNullPointerDereference(*this, LHSExpr); @@ -11864,8 +11867,8 @@ } bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, - SourceLocation Loc, - QualType DstType, QualType SrcType, + SourceLocation Loc, QualType DstType, + VarDecl *DstVarDecl, QualType SrcType, Expr *SrcExpr, AssignmentAction Action, bool *Complained) { if (Complained) @@ -12051,6 +12054,16 @@ HandleFunctionTypeMismatch(FDiag, SecondType, FirstType); Diag(Loc, FDiag); + + // Emit original location of a variable declaration which is on the LHS + if (DiagKind == diag::ext_nested_pointer_qualifier_mismatch && DstVarDecl) { + SourceRange DstVarDeclSR = DstVarDecl->getSourceRange(); + PartialDiagnostic Note = + PDiag(diag::note_nested_pointer_discarded_qualifier); + Note << DstVarDeclSR; + Diag(DstVarDeclSR.getBegin(), Note); + } + if (DiagKind == diag::warn_incompatible_qualified_id && PDecl && IFace && !IFace->hasDefinition()) Diag(IFace->getLocation(), diag::not_incomplete_class_and_qualified_id) Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -6638,11 +6638,11 @@ CurInit = CurInitExprRes; bool Complained; - if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), - Step->Type, SourceType, - InitialCurInit.get(), - getAssignmentAction(Entity, true), - &Complained)) { + if (S.DiagnoseAssignmentResult( + ConvTy, Kind.getLocation(), Step->Type, + Entity.getDecl() ? dyn_cast(Entity.getDecl()) : nullptr, + SourceType, InitialCurInit.get(), + getAssignmentAction(Entity, true), &Complained)) { PrintInitLocationNote(S, Entity); return ExprError(); } else if (Complained) Index: lib/Sema/SemaPseudoObject.cpp =================================================================== --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -746,7 +746,7 @@ ExprResult opResult = op; Sema::AssignConvertType assignResult = S.CheckSingleAssignmentConstraints(paramType, opResult); - if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, + if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, nullptr, op->getType(), opResult.get(), Sema::AA_Assigning)) return ExprError(); Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -2604,7 +2604,8 @@ if (ExprRes.isInvalid()) return StmtError(); E = ExprRes.get(); - if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) + if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, nullptr, ETy, E, + AA_Passing)) return StmtError(); }