From: Sean Hunt Date: Sat, 28 Nov 2009 04:44:28 +0000 (+0000) Subject: Add Parser support for C++0x literal operators ('operator "" i'). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0486d746019f8310589b1f0d92edcc4bb3916b33;p=clang Add Parser support for C++0x literal operators ('operator "" i'). DeclarationName can't handle them yet, so right now Parser just errors out on them. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90027 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 691c571f82..7de5b20d6e 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -242,6 +242,10 @@ def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; // C++ operator overloading def err_operator_missing_type_specifier : Error< "missing type specifier after 'operator'">; +def err_operator_string_not_empty : Error< + "string literal after 'operator' must be '\"\"'">; +def err_unsupported_literal_operator : Error< + "C++0x literal operator support is currently under development">; // Classes. def err_anon_type_definition : Error< diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 7e7d0b3f28..fe899b3fdb 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -484,6 +484,8 @@ public: IK_OperatorFunctionId, /// \brief A conversion function name, e.g., operator int. IK_ConversionFunctionId, + /// \brief A user-defined literal name, e.g., operator "" _i. + IK_LiteralOperatorId, /// \brief A constructor name. IK_ConstructorName, /// \brief A destructor name. @@ -495,7 +497,8 @@ public: /// \brief Anonymous union that holds extra data associated with the /// parsed unqualified-id. union { - /// \brief When Kind == IK_Identifier, the parsed identifier. + /// \brief When Kind == IK_Identifier, the parsed identifier, or when Kind + /// == IK_UserLiteralId, the identifier suffix. IdentifierInfo *Identifier; /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator @@ -607,6 +610,22 @@ public: EndLocation = EndLoc; ConversionFunctionId = Ty; } + + /// \brief Specific that this unqualified-id was parsed as a + /// literal-operator-id. + /// + /// \param Id the parsed identifier. + /// + /// \param OpLoc the location of the 'operator' keyword. + /// + /// \param IdLoc the location of the identifier. + void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc, + SourceLocation IdLoc) { + Kind = IK_LiteralOperatorId; + Identifier = const_cast(Id); + StartLocation = OpLoc; + EndLocation = IdLoc; + } /// \brief Specify that this unqualified-id was parsed as a constructor name. /// diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 157d8837a9..6aca1cbbcc 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1031,6 +1031,27 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations); return false; } + + // Parse a literal-operator-id. + // + // literal-operator-id: [C++0x 13.5.8] + // operator "" identifier + + if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) { + if (Tok.getLength() != 2) + Diag(Tok.getLocation(), diag::err_operator_string_not_empty); + ConsumeStringToken(); + + if (Tok.isNot(tok::identifier)) { + Diag(Tok.getLocation(), diag::err_expected_ident); + return true; + } + + IdentifierInfo *II = Tok.getIdentifierInfo(); + Result.setLiteralOperatorId(II, KeywordLoc, ConsumeToken()); + Diag(KeywordLoc, diag::err_unsupported_literal_operator); + return true; + } // Parse a conversion-function-id. // diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 153c15b889..fe73785a7f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1765,7 +1765,10 @@ DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) { case UnqualifiedId::IK_OperatorFunctionId: return Context.DeclarationNames.getCXXOperatorName( Name.OperatorFunctionId.Operator); - + + case UnqualifiedId::IK_LiteralOperatorId: + assert(false && "We don't support these; Parse shouldn't have allowed propagation"); + case UnqualifiedId::IK_ConversionFunctionId: { QualType Ty = GetTypeFromParser(Name.ConversionFunctionId); if (Ty.isNull()) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index aeb9a8860c..a6bb401a88 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2823,6 +2823,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, switch (Name.getKind()) { case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_ConversionFunctionId: break; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 00dc809f51..afce5e33ba 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -879,6 +879,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, switch (D.getName().getKind()) { case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_TemplateId: T = ConvertDeclSpecToType(D, *this); diff --git a/test/Parser/cxx0x-literal-operators.cpp b/test/Parser/cxx0x-literal-operators.cpp new file mode 100644 index 0000000000..b01cf06edb --- /dev/null +++ b/test/Parser/cxx0x-literal-operators.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s + +void operator "" (); // expected-error {{expected identifier}} +void operator "k" foo(); // expected-error {{string literal after 'operator' must be '""'}} \ + // expected-error {{C++0x literal operator support is currently under development}} \ No newline at end of file