]> granicus.if.org Git - clang/commitdiff
Add Parser support for C++0x literal operators ('operator "" i').
authorSean Hunt <rideau3@gmail.com>
Sat, 28 Nov 2009 04:44:28 +0000 (04:44 +0000)
committerSean Hunt <rideau3@gmail.com>
Sat, 28 Nov 2009 04:44:28 +0000 (04:44 +0000)
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

include/clang/Basic/DiagnosticParseKinds.td
include/clang/Parse/DeclSpec.h
lib/Parse/ParseExprCXX.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaType.cpp
test/Parser/cxx0x-literal-operators.cpp [new file with mode: 0644]

index 691c571f82cc3123038a5b0fa519aafc80db5170..7de5b20d6ee8a29c7c504e33b8924c533e26a50a 100644 (file)
@@ -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<
index 7e7d0b3f28e84088d53d80934628610984da92d1..fe899b3fdb17f22713460c15dd5e32bd34cfd5bb 100644 (file)
@@ -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<IdentifierInfo *>(Id);
+    StartLocation = OpLoc;
+    EndLocation = IdLoc;
+  }
   
   /// \brief Specify that this unqualified-id was parsed as a constructor name.
   ///
index 157d8837a934b192a2e8c523aae2fb403a6de450..6aca1cbbcc46761aa77dc37ff8f941878214ba70 100644 (file)
@@ -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.
   //
index 153c15b889a44f0fa296ca80f18e7106d0d65670..fe73785a7f155ee02638883ef585fdbb9e132ba4 100644 (file)
@@ -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())
index aeb9a8860c82cc9c69d8b301361db2db36b92f1a..a6bb401a88d08ba64dc1e3b620559f880ea7d9eb 100644 (file)
@@ -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;
       
index 00dc809f51a822c641cca2b3fcc3519286a30788..afce5e33ba6b51522369388e3073912cbbc7aa03 100644 (file)
@@ -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 (file)
index 0000000..b01cf06
--- /dev/null
@@ -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