From eeae8f072748affce25ab4064982626361293390 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 28 Mar 2009 00:41:23 +0000 Subject: [PATCH] Make our diagnostics about the obsolete GNU designated-initializer syntax into extension warnings, and provide code-modification hints showing how to fix the problem. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67885 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 14 +++++++------- include/clang/Basic/DiagnosticParseKinds.td | 4 ++-- include/clang/Parse/Action.h | 8 ++++---- lib/AST/ASTContext.cpp | 1 - lib/AST/Expr.cpp | 2 +- lib/Parse/ParseInit.cpp | 17 +++++++++++++---- lib/Sema/Sema.h | 2 +- lib/Sema/SemaInit.cpp | 4 ++-- test/Sema/designated-initializers.c | 3 ++- 9 files changed, 32 insertions(+), 23 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 9ce86ef12d..f652f1d26e 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1860,9 +1860,9 @@ class DesignatedInitExpr : public Expr { /// expression. SourceLocation EqualOrColonLoc; - /// Whether this designated initializer used the GNU deprecated ':' + /// Whether this designated initializer used the GNU deprecated /// syntax rather than the C99 '=' syntax. - bool UsesColonSyntax : 1; + bool GNUSyntax : 1; /// The number of designators in this initializer expression. unsigned NumDesignators : 15; @@ -1873,10 +1873,10 @@ class DesignatedInitExpr : public Expr { unsigned NumSubExprs : 16; DesignatedInitExpr(QualType Ty, unsigned NumDesignators, - SourceLocation EqualOrColonLoc, bool UsesColonSyntax, + SourceLocation EqualOrColonLoc, bool GNUSyntax, unsigned NumSubExprs) : Expr(DesignatedInitExprClass, Ty), - EqualOrColonLoc(EqualOrColonLoc), UsesColonSyntax(UsesColonSyntax), + EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax), NumDesignators(NumDesignators), NumSubExprs(NumSubExprs) { } public: @@ -2022,7 +2022,7 @@ public: unsigned NumDesignators, Expr **IndexExprs, unsigned NumIndexExprs, SourceLocation EqualOrColonLoc, - bool UsesColonSyntax, Expr *Init); + bool GNUSyntax, Expr *Init); /// @brief Returns the number of designators in this initializer. unsigned size() const { return NumDesignators; } @@ -2041,8 +2041,8 @@ public: SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } /// @brief Determines whether this designated initializer used the - /// GNU 'fieldname:' syntax or the C99 '=' syntax. - bool usesColonSyntax() const { return UsesColonSyntax; } + /// deprecated GNU syntax for designated initializers. + bool usesGNUSyntax() const { return GNUSyntax; } /// @brief Retrieve the initializer value. Expr *getInit() const { diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 4f1b1abe48..7b264d3461 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -57,10 +57,10 @@ def ext_gnu_conditional_expr : Extension< def ext_gnu_empty_initializer : Extension< "use of GNU empty initializer extension">; def ext_gnu_array_range : Extension<"use of GNU array range extension">; -def ext_gnu_missing_equal_designator : Extension< +def ext_gnu_missing_equal_designator : ExtWarn< "use of GNU 'missing =' extension in designator">; def err_expected_equal_designator : Error<"expected '=' or another designator">; -def ext_gnu_old_style_field_designator : Extension< +def ext_gnu_old_style_field_designator : ExtWarn< "use of GNU old-style field designator extension">; def ext_gnu_case_range : Extension<"use of GNU case range extension">; diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index b602934cc3..f284ca0a75 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -703,15 +703,15 @@ public: /// @param Loc The location of the '=' or ':' prior to the /// initialization expression. /// - /// @param UsedColonSyntax If true, then this designated initializer - /// used the deprecated GNU syntax @c fieldname:foo rather than the - /// C99 syntax @c .fieldname=foo. + /// @param GNUSyntax If true, then this designated initializer used + /// the deprecated GNU syntax @c fieldname:foo or @c [expr]foo rather + /// than the C99 syntax @c .fieldname=foo or @c [expr]=foo. /// /// @param Init The value that the entity (or entities) described by /// the designation will be initialized with. virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig, SourceLocation Loc, - bool UsedColonSyntax, + bool GNUSyntax, OwningExprResult Init) { return ExprEmpty(); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 2fc6a7d527..da6e049732 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -89,7 +89,6 @@ ASTContext::~ASTContext() { GlobalNestedNameSpecifier->Destroy(*this); TUDecl->Destroy(*this); - } void ASTContext::PrintStats() const { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 92310902e2..08ab5440b1 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1534,7 +1534,7 @@ SourceRange DesignatedInitExpr::getSourceRange() const { Designator &First = *const_cast(this)->designators_begin(); if (First.isFieldDesignator()) { - if (UsesColonSyntax) + if (GNUSyntax) StartLoc = SourceLocation::getFromRawEncoding(First.Field.FieldLoc); else StartLoc = SourceLocation::getFromRawEncoding(First.Field.DotLoc); diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 3a42e50a9c..7837a0c7fd 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -64,14 +64,22 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { // Handle it as a field designator. Otherwise, this must be the start of a // normal expression. if (Tok.is(tok::identifier)) { - Diag(Tok, diag::ext_gnu_old_style_field_designator); - const IdentifierInfo *FieldName = Tok.getIdentifierInfo(); + + std::string NewSyntax("."); + NewSyntax += FieldName->getName(); + NewSyntax += " = "; + SourceLocation NameLoc = ConsumeToken(); // Eat the identifier. assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!"); SourceLocation ColonLoc = ConsumeToken(); + Diag(Tok, diag::ext_gnu_old_style_field_designator) + << CodeModificationHint::CreateReplacement(SourceRange(NameLoc, + ColonLoc), + NewSyntax); + Designation D; D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc)); return Actions.ActOnDesignatedInitializer(D, ColonLoc, true, @@ -209,8 +217,9 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { if (Desig.getNumDesignators() == 1 && (Desig.getDesignator(0).isArrayDesignator() || Desig.getDesignator(0).isArrayRangeDesignator())) { - Diag(Tok, diag::ext_gnu_missing_equal_designator); - return Actions.ActOnDesignatedInitializer(Desig, SourceLocation(), + Diag(Tok, diag::ext_gnu_missing_equal_designator) + << CodeModificationHint::CreateInsertion(Tok.getLocation(), "="); + return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(), true, ParseInitializer()); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 8dee4f19a2..76740e8dd9 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1285,7 +1285,7 @@ public: virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig, SourceLocation Loc, - bool UsedColonSyntax, + bool GNUSyntax, OwningExprResult Init); virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 600dc34351..fbf3ae2a78 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1548,7 +1548,7 @@ CheckArrayDesignatorExpr(Sema &Self, Expr *Index, llvm::APSInt &Value) { Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, SourceLocation Loc, - bool UsedColonSyntax, + bool GNUSyntax, OwningExprResult Init) { typedef DesignatedInitExpr::Designator ASTDesignator; @@ -1622,7 +1622,7 @@ Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, DesignatedInitExpr *DIE = DesignatedInitExpr::Create(Context, &Designators[0], Designators.size(), &InitExpressions[0], InitExpressions.size(), - Loc, UsedColonSyntax, + Loc, GNUSyntax, static_cast(Init.release())); return Owned(DIE); } diff --git a/test/Sema/designated-initializers.c b/test/Sema/designated-initializers.c index cfbe80224b..f4170c267d 100644 --- a/test/Sema/designated-initializers.c +++ b/test/Sema/designated-initializers.c @@ -18,6 +18,7 @@ int iarray2[10] = { }; int iarray3[10] = { + [3] 2, // expected-warning{{use of GNU 'missing =' extension in designator}} [5 ... 12] = 2 // expected-error{{array designator index (12) exceeds array bounds (10)}} }; @@ -28,7 +29,7 @@ struct point { struct point p1 = { .y = 1.0, - x: 2.0, + x: 2.0, // expected-warning{{}} .a = 4.0, // expected-error{{field designator 'a' does not refer to any field in type 'struct point'}} };