r196443 - Reject template-ids containing literal-operator-ids that have a dependent
Richard Smith
richard-llvm at metafoo.co.uk
Wed Dec 4 16:58:34 PST 2013
Author: rsmith
Date: Wed Dec 4 18:58:33 2013
New Revision: 196443
URL: http://llvm.org/viewvc/llvm-project?rev=196443&view=rev
Log:
Reject template-ids containing literal-operator-ids that have a dependent
nested-name-specifier, rather than crashing. (In fact, reject all
literal-operator-ids that have a non-namespace nested-name-specifier). The
grammar doesn't allow these in some cases, and in other cases does allow them
but instantiation will always fail.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=196443&r1=196442&r2=196443&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Dec 4 18:58:33 2013
@@ -6009,6 +6009,8 @@ def err_operator_delete_param_type : Err
// C++ literal operators
def err_literal_operator_outside_namespace : Error<
"literal operator %0 must be in a namespace or global scope">;
+def err_literal_operator_id_outside_namespace : Error<
+ "non-namespace scope '%0' cannot have a literal operator member">;
def err_literal_operator_default_argument : Error<
"literal operator cannot have a default argument">;
// FIXME: This diagnostic sucks
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=196443&r1=196442&r2=196443&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Dec 4 18:58:33 2013
@@ -2478,6 +2478,7 @@ public:
bool RValueThis, unsigned ThisQuals);
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
+ bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id);
LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
ArrayRef<QualType> ArgTys,
bool AllowRaw,
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=196443&r1=196442&r2=196443&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Dec 4 18:58:33 2013
@@ -287,19 +287,23 @@ bool Parser::ParseOptionalCXXScopeSpecif
TentativeParsingAction TPA(*this);
SourceLocation TemplateKWLoc = ConsumeToken();
-
+
UnqualifiedId TemplateName;
if (Tok.is(tok::identifier)) {
// Consume the identifier.
TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
} else if (Tok.is(tok::kw_operator)) {
- if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
+ // We don't need to actually parse the unqualified-id in this case,
+ // because a simple-template-id cannot start with 'operator', but
+ // go ahead and parse it anyway for consistency with the case where
+ // we already annotated the template-id.
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
TemplateName)) {
TPA.Commit();
break;
}
-
+
if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
Diag(TemplateName.getSourceRange().getBegin(),
@@ -2131,9 +2135,10 @@ bool Parser::ParseUnqualifiedIdOperator(
}
Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc);
- return false;
+
+ return Actions.checkLiteralOperatorId(SS, Result);
}
-
+
// Parse a conversion-function-id.
//
// conversion-function-id: [C++ 12.3.2]
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=196443&r1=196442&r2=196443&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Dec 4 18:58:33 2013
@@ -333,6 +333,34 @@ ParsedType Sema::getDestructorType(const
return ParsedType();
}
+bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
+ const UnqualifiedId &Name) {
+ assert(Name.getKind() == UnqualifiedId::IK_LiteralOperatorId);
+
+ if (!SS.isValid())
+ return false;
+
+ switch (SS.getScopeRep()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ // Per C++11 [over.literal]p2, literal operators can only be declared at
+ // namespace scope. Therefore, this unqualified-id cannot name anything.
+ // Reject it early, because we have no AST representation for this in the
+ // case where the scope is dependent.
+ Diag(Name.getLocStart(), diag::err_literal_operator_id_outside_namespace)
+ << SS.getScopeRep();
+ return true;
+
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ return false;
+ }
+
+ llvm_unreachable("unknown nested name specifier kind");
+}
+
/// \brief Build a C++ typeid expression with a type operand.
ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=196443&r1=196442&r2=196443&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Dec 4 18:58:33 2013
@@ -2914,8 +2914,7 @@ TemplateNameKind Sema::ActOnDependentTem
return TNK_Function_template;
case UnqualifiedId::IK_LiteralOperatorId:
- llvm_unreachable(
- "We don't support these; Parse shouldn't have allowed propagation");
+ llvm_unreachable("literal operator id cannot have a dependent scope");
default:
break;
Modified: cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp?rev=196443&r1=196442&r2=196443&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx11-user-defined-literals.cpp Wed Dec 4 18:58:33 2013
@@ -141,3 +141,27 @@ namespace PR14950 {
int operator"" _b(); // expected-error {{no function template matches function template specialization}}
int main() { return 0_b; } // expected-error {{no matching literal operator for call to 'operator "" _b'}}
}
+
+namespace bad_names {
+ template<char...> int operator""_x();
+
+ template<typename T> void f() {
+ class T:: // expected-error {{anonymous class}} expected-warning {{does not declare anything}}
+ operator // expected-error {{expected identifier}}
+ ""_q<'a'>;
+
+ T::template operator""_q<'a'>(); // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} expected-error +{{}}
+ T::template operator""_q<'a'>::X; // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} expected-error +{{}}
+ T::operator""_q<'a'>(); // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} expected-error +{{}}
+ typename T::template operator""_q<'a'> a; // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} expected-error +{{}}
+ typename T::operator""_q(""); // expected-error +{{}} expected-note {{to match}}
+ T::operator""_q(""); // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}}
+
+ bad_names::operator""_x<'a', 'b', 'c'>();
+ };
+
+ struct S {};
+ void g() {
+ S::operator""_q(); // expected-error {{non-namespace scope 'S::' cannot have a literal operator member}}
+ }
+}
More information about the cfe-commits
mailing list