diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ae97b24f853a..bce0a3744603 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8783,6 +8783,19 @@ namespace { } } +/// Determine whether the given expression was formed from the token '0'. This +/// test is necessary to determine whether an initializer is really a +/// pure-specifier. +static bool isZeroToken(Sema &S, Expr *E) { + auto *IL = dyn_cast(E); + if (!IL || !!IL->getValue() || + !IL->getType()->isSpecificBuiltinType(BuiltinType::Int)) + return false; + + SmallString<8> Buffer; + return S.PP.getSpelling(E->getLocStart(), Buffer) == "0"; +} + /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. @@ -8799,9 +8812,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // With declarators parsed the way they are, the parser cannot // distinguish between a normal initializer and a pure-specifier. // Thus this grotesque test. - IntegerLiteral *IL; - if ((IL = dyn_cast(Init)) && IL->getValue() == 0 && - Context.getCanonicalType(IL->getType()) == Context.IntTy) + // + // FIXME: The parser should instead treat anything that looks like a + // pure-specifier as a pure-specifier, and Sema should convert it to an + // initializer when necessary, rather than doing things this way around. + if (!DirectInit && isZeroToken(*this, Init)) CheckPureMethod(Method, Init->getSourceRange()); else { Diag(Method->getLocation(), diag::err_member_function_initialization) diff --git a/clang/test/Parser/cxx-class.cpp b/clang/test/Parser/cxx-class.cpp index 38eef1756d0f..9e907f1b1c12 100644 --- a/clang/test/Parser/cxx-class.cpp +++ b/clang/test/Parser/cxx-class.cpp @@ -24,6 +24,16 @@ public: ; // expected-warning{{extra ';' inside a class}} virtual int vf() const volatile = 0; + + virtual int vf0() = 0l; // expected-error {{does not look like a pure-specifier}} + virtual int vf1() = 1; // expected-error {{does not look like a pure-specifier}} + virtual int vf2() = 00; // expected-error {{does not look like a pure-specifier}} + virtual int vf3() = 0x0; // expected-error {{does not look like a pure-specifier}} + virtual int vf4() = 0.0; // expected-error {{does not look like a pure-specifier}} + virtual int vf5(){0}; // expected-error +{{}} expected-warning {{unused}} + virtual int vf5a(){0;}; // function definition, expected-warning {{unused}} + virtual int vf6()(0); // expected-error +{{}} expected-note +{{}} + virtual int vf7() = { 0 }; // expected-error {{does not look like a pure-specifier}} private: int x,f(),y,g();