]> granicus.if.org Git - clang/commitdiff
Sema: Do not allow overloading between methods based on restrict
authorDavid Majnemer <david.majnemer@gmail.com>
Sun, 3 Nov 2013 23:51:28 +0000 (23:51 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sun, 3 Nov 2013 23:51:28 +0000 (23:51 +0000)
If the sole distinction between two declarations is that one has a
__restrict qualifier then we should not consider it to be an overload.

Instead, we will consider it as an incompatible redeclaration which is
similar to how MSVC, ICC and GCC would handle it.

This fixes PR17786.

N.B. We must not mangle in __restrict into method qualifiers becase we
don't allow overloading between such declarations anymore.  To do
otherwise would be a violation of the Itanium ABI.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193964 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ItaniumMangle.cpp
lib/Sema/SemaOverload.cpp
test/CodeGenCXX/mangle.cpp
test/SemaCXX/overload-decl.cpp

index 21a6c107bb7db96406500ba8e5c0d33c020e5f6c..953bff20ad6690ddfad0ca7414e837c47e8dfac6 100644 (file)
@@ -1239,7 +1239,12 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
 
   Out << 'N';
   if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
-    mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
+    Qualifiers MethodQuals =
+        Qualifiers::fromCVRMask(Method->getTypeQualifiers());
+    // We do not consider restrict a distinguishing attribute for overloading
+    // purposes so we must not mangle it.
+    MethodQuals.removeRestrict();
+    mangleQualifiers(MethodQuals);
     mangleRefQualifier(Method->getRefQualifier());
   }
   
index 20cfb00584d20f0971def7a5179bc84a9321b65a..c6bcf449b7762c98a8fc13b81cd1e38a90aa4d93 100644 (file)
@@ -1071,11 +1071,16 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
     // function yet (because we haven't yet resolved whether this is a static
     // or non-static member function). Add it now, on the assumption that this
     // is a redeclaration of OldMethod.
+    unsigned OldQuals = OldMethod->getTypeQualifiers();
     unsigned NewQuals = NewMethod->getTypeQualifiers();
     if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&
         !isa<CXXConstructorDecl>(NewMethod))
       NewQuals |= Qualifiers::Const;
-    if (OldMethod->getTypeQualifiers() != NewQuals)
+
+    // We do not allow overloading based off of '__restrict'.
+    OldQuals &= ~Qualifiers::Restrict;
+    NewQuals &= ~Qualifiers::Restrict;
+    if (OldQuals != NewQuals)
       return true;
   }
 
index 4e6dbf5397abbf87504ebc2a43a30c0536baebbf..d836f36c1818baf0007daead96bd597c2195bb0c 100644 (file)
@@ -942,3 +942,12 @@ namespace test43 {
   void g(zed<&foo::bar>*)
   {}
 }
+
+namespace test44 {
+  struct foo { void bar() __restrict { }; } obj;
+
+  void f() {
+    obj.bar();
+  }
+  // CHECK-LABEL: define linkonce_odr void @_ZN6test443foo3barEv(%"struct.test44::foo"* %this)
+}
index 0153620d45b9b2542e8017154f2a454e1de25666..fdb14cb173eb21d7e86d1e41a5b49fde743b5b24 100644 (file)
@@ -29,6 +29,11 @@ class X {
   static void g(float); // expected-note {{previous declaration is here}}
   static void g(int); // expected-error {{static and non-static member functions with the same parameter types cannot be overloaded}}
   static void g(float); // expected-error {{class member cannot be redeclared}}
+
+  void h(); // expected-note {{previous declaration is here}} \
+               expected-note {{previous declaration is here}}
+  void h() __restrict; // expected-error {{class member cannot be redeclared}} \
+                          expected-error {{conflicting types for 'h'}}
 };
 
 int main() {} // expected-note {{previous definition is here}}