diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 81df5e23515a36ec4ddcc8f367edf029c235ed7c..55e1d694928e5adcc408bccdca45f8bc7eb05d31 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -946,6 +946,18 @@ private:
     ClassOrNamespace *_binding;
 };
 
+static bool isTypeTypedefed(const FullySpecifiedType &originalTy,
+                            const FullySpecifiedType &typedefedTy)
+{
+    return ! originalTy.isEqualTo(typedefedTy);
+}
+
+static bool areOriginalAndTypedefedTypePointer(const FullySpecifiedType &originalTy,
+                                               const FullySpecifiedType &typedefedTy)
+{
+    return originalTy->isPointerType() && typedefedTy->isPointerType();
+}
+
 ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
                                                     int accessOp,
                                                     bool *replacedDotOperator) const
@@ -1035,23 +1047,12 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
             }
         } else if (accessOp == T_DOT) {
             if (replacedDotOperator) {
-                *replacedDotOperator = originalType->isPointerType() || ty->isPointerType();
-                // replace . with ->
-                if (PointerType *ptrTy = originalType->asPointerType()) {
-                    // case when original type is a pointer and
-                    // typedef is for type
-                    // e.g.:
-                    // typedef S SType;
-                    // SType *p;
-                    ty = ptrTy->elementType();
-                }
-                else if (PointerType *ptrTy = ty->asPointerType()) {
-                    // case when original type is a type and
-                    // typedef is for pointer of type
-                    // e.g.:
-                    // typedef S* SPTR;
-                    // SPTR p;
-                    ty = ptrTy->elementType();
+                if (! isTypeTypedefed(originalType, ty)
+                        || ! areOriginalAndTypedefedTypePointer(originalType, ty)) {
+                    *replacedDotOperator = originalType->isPointerType() || ty->isPointerType();
+                    if (PointerType *ptrTy = ty->asPointerType()) {
+                        ty = ptrTy->elementType();
+                    }
                 }
             }
 
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index c1012f3527761429e89fdd54795c6498d56418d1..a3b56ca10844e1f940773afefd3ed4e7d17f5910 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -1473,7 +1473,61 @@ void CppToolsPlugin::test_completion_member_access_operator_1()
     QVERIFY(replaceAccessOperator);
 }
 
-void CppToolsPlugin::test_completion_typedef_of_type_and_replace_access_operator()
+void CppToolsPlugin::test_completion_typedef_of_type_and_decl_of_type_no_replace_access_operator()
+{
+    TestData data;
+    data.srcText = "\n"
+            "struct S { int m; };\n"
+            "typedef S SType;\n"
+            "SType p;\n"
+            "@\n"
+            "}\n"
+            ;
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("p.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    bool replaceAccessOperator = false;
+    QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+    QCOMPARE(completions.size(), 2);
+    QVERIFY(completions.contains(QLatin1String("S")));
+    QVERIFY(completions.contains(QLatin1String("m")));
+    QVERIFY(! replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_typedef_of_pointer_and_decl_of_pointer_no_replace_access_operator()
+{
+    TestData data;
+    data.srcText = "\n"
+            "struct S { int m; };\n"
+            "typedef S *SType;\n"
+            "SType *p;\n"
+            "@\n"
+            "}\n"
+            ;
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("p.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    bool replaceAccessOperator = false;
+    QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+    QCOMPARE(completions.size(), 0);
+    QVERIFY(! replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_typedef_of_type_and_decl_of_pointer_replace_access_operator()
 {
     TestData data;
     data.srcText = "\n"
@@ -1501,7 +1555,7 @@ void CppToolsPlugin::test_completion_typedef_of_type_and_replace_access_operator
     QVERIFY(replaceAccessOperator);
 }
 
-void CppToolsPlugin::test_completion_typedef_of_pointer_of_type_and_replace_access_operator()
+void CppToolsPlugin::test_completion_typedef_of_pointer_and_decl_of_type_replace_access_operator()
 {
     TestData data;
     data.srcText = "\n"
@@ -1529,6 +1583,116 @@ void CppToolsPlugin::test_completion_typedef_of_pointer_of_type_and_replace_acce
     QVERIFY(replaceAccessOperator);
 }
 
+void CppToolsPlugin::test_completion_predecl_typedef_of_type_and_decl_of_pointer_replace_access_operator()
+{
+    TestData data;
+    data.srcText = "\n"
+            "typedef struct S SType;\n"
+            "struct S { int m; };\n"
+            "SType *p;\n"
+            "@\n"
+            "}\n"
+            ;
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("p.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    bool replaceAccessOperator = false;
+    QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+    QCOMPARE(completions.size(), 2);
+    QVERIFY(completions.contains(QLatin1String("S")));
+    QVERIFY(completions.contains(QLatin1String("m")));
+    QVERIFY(replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_predecl_typedef_of_type_and_decl_type_no_replace_access_operator()
+{
+    TestData data;
+    data.srcText = "\n"
+            "typedef struct S SType;\n"
+            "struct S { int m; };\n"
+            "SType p;\n"
+            "@\n"
+            "}\n"
+            ;
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("p.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    bool replaceAccessOperator = false;
+    QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+    QCOMPARE(completions.size(), 2);
+    QVERIFY(completions.contains(QLatin1String("S")));
+    QVERIFY(completions.contains(QLatin1String("m")));
+    QVERIFY(! replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_predecl_typedef_of_pointer_and_decl_of_pointer_no_replace_access_operator()
+{
+    TestData data;
+    data.srcText = "\n"
+            "typedef struct S *SType;\n"
+            "struct S { int m; };\n"
+            "SType *p;\n"
+            "@\n"
+            "}\n"
+            ;
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("p.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    bool replaceAccessOperator = false;
+    QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+    QCOMPARE(completions.size(), 0);
+    QVERIFY(! replaceAccessOperator);
+}
+
+void CppToolsPlugin::test_completion_predecl_typedef_of_pointer_and_decl_of_type_replace_access_operator()
+{
+    TestData data;
+    data.srcText = "\n"
+            "typedef struct S *SType;\n"
+            "struct S { int m; };\n"
+            "SType p;\n"
+            "@\n"
+            "}\n"
+            ;
+    setup(&data);
+
+    Utils::ChangeSet change;
+    QString txt = QLatin1String("p.");
+    change.insert(data.pos, txt);
+    QTextCursor cursor(data.doc);
+    change.apply(&cursor);
+    data.pos += txt.length();
+
+    bool replaceAccessOperator = false;
+    QStringList completions = getCompletions(data, &replaceAccessOperator);
+
+    QCOMPARE(completions.size(), 2);
+    QVERIFY(completions.contains(QLatin1String("S")));
+    QVERIFY(completions.contains(QLatin1String("m")));
+    QVERIFY(replaceAccessOperator);
+}
+
 void CppToolsPlugin::test_completion_typedef_of_pointer()
 {
     TestData data;
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index a8ab4bbc291e1b76424d3832c28b58e6cd0ec0d8..5e4d14385068056abb2394a054737a66b72a2e79 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -113,8 +113,17 @@ private slots:
     void test_completion_instantiate_template_with_default_argument_type();
     void test_completion_instantiate_template_with_default_argument_type_as_template();
     void test_completion_member_access_operator_1();
-    void test_completion_typedef_of_type_and_replace_access_operator();
-    void test_completion_typedef_of_pointer_of_type_and_replace_access_operator();
+
+    void test_completion_typedef_of_type_and_decl_of_type_no_replace_access_operator();
+    void test_completion_typedef_of_pointer_and_decl_of_pointer_no_replace_access_operator();
+    void test_completion_typedef_of_type_and_decl_of_pointer_replace_access_operator();
+    void test_completion_typedef_of_pointer_and_decl_of_type_replace_access_operator();
+
+    void test_completion_predecl_typedef_of_type_and_decl_of_pointer_replace_access_operator();
+    void test_completion_predecl_typedef_of_type_and_decl_type_no_replace_access_operator();
+    void test_completion_predecl_typedef_of_pointer_and_decl_of_pointer_no_replace_access_operator();
+    void test_completion_predecl_typedef_of_pointer_and_decl_of_type_replace_access_operator();
+
     void test_completion_typedef_of_pointer();
     void test_completion_typedef_of_pointer_inside_function();
     void test_completion_typedef_is_inside_function_before_declaration_block();