balazske created this revision.
Herald added subscribers: cfe-commits, gamesh411, Szelethus, dkrupp.
Herald added a reviewer: martong.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added a project: clang.

The default expression of a parameter variable should be imported before
the parameter variable object is created. Otherwise the function is created
with an incomplete parameter variable (default argument is nullptr) and in
this intermediary state the expression is imported. This import can have
a reference to the incomplete parameter variable that causes crash.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65577

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/test/Analysis/Inputs/ctu-other.cpp
  clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
  clang/test/Analysis/ctu-main.cpp


Index: clang/test/Analysis/ctu-main.cpp
===================================================================
--- clang/test/Analysis/ctu-main.cpp
+++ clang/test/Analysis/ctu-main.cpp
@@ -112,6 +112,8 @@
   clang_analyzer_eval(obj->fvcl(1) == 8);      // expected-warning{{FALSE}} 
expected-warning{{TRUE}}
 }
 
+extern int testDefParmIncompleteImport(int);
+
 int main() {
   clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}}
   clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}}
@@ -144,4 +146,6 @@
   clang_analyzer_eval(extSubSCN.a == 1); // expected-warning{{TRUE}}
   // clang_analyzer_eval(extSCC.a == 7); // TODO
   clang_analyzer_eval(extU.a == 4); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(testDefParmIncompleteImport(9) == 9); // 
expected-warning{{TRUE}}
 }
Index: clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
===================================================================
--- clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
+++ clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
@@ -25,3 +25,4 @@
 c:@extSubSCN ctu-other.cpp.ast
 c:@extSCC ctu-other.cpp.ast
 c:@extU ctu-other.cpp.ast
+c:@F@testDefParmIncompleteImport#I# ctu-other.cpp.ast
Index: clang/test/Analysis/Inputs/ctu-other.cpp
===================================================================
--- clang/test/Analysis/Inputs/ctu-other.cpp
+++ clang/test/Analysis/Inputs/ctu-other.cpp
@@ -131,3 +131,22 @@
   const unsigned int b;
 };
 U extU = {.a = 4};
+
+struct DefParmContext {
+  static const int I;
+  int f();
+};
+
+int fDefParm(int I = DefParmContext::I) {
+  return I;
+}
+
+int testDefParmIncompleteImport(int I) {
+  return fDefParm(I);
+}
+
+const int DefParmContext::I = 0;
+
+int DefParmContext::f() {
+  return fDefParm();
+}
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -3842,6 +3842,15 @@
   else
     return Imp.takeError();
 
+  Expr *DefaultArg = nullptr;
+  if (D->hasUninstantiatedDefaultArg()) {
+    if (Error Err = importInto(DefaultArg, D->getUninstantiatedDefaultArg()))
+      return std::move(Err);
+  } else if (D->hasDefaultArg()) {
+    if (Error Err = importInto(DefaultArg, D->getDefaultArg()))
+      return std::move(Err);
+  }
+
   ParmVarDecl *ToParm;
   if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC,
                               ToInnerLocStart, ToLocation,
@@ -3853,19 +3862,12 @@
   // Set the default argument.
   ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
   ToParm->setKNRPromoted(D->isKNRPromoted());
-
   if (D->hasUninstantiatedDefaultArg()) {
-    if (auto ToDefArgOrErr = import(D->getUninstantiatedDefaultArg()))
-      ToParm->setUninstantiatedDefaultArg(*ToDefArgOrErr);
-    else
-      return ToDefArgOrErr.takeError();
+    ToParm->setUninstantiatedDefaultArg(DefaultArg);
   } else if (D->hasUnparsedDefaultArg()) {
     ToParm->setUnparsedDefaultArg();
   } else if (D->hasDefaultArg()) {
-    if (auto ToDefArgOrErr = import(D->getDefaultArg()))
-      ToParm->setDefaultArg(*ToDefArgOrErr);
-    else
-      return ToDefArgOrErr.takeError();
+    ToParm->setDefaultArg(DefaultArg);
   }
 
   if (D->isObjCMethodParameter()) {


Index: clang/test/Analysis/ctu-main.cpp
===================================================================
--- clang/test/Analysis/ctu-main.cpp
+++ clang/test/Analysis/ctu-main.cpp
@@ -112,6 +112,8 @@
   clang_analyzer_eval(obj->fvcl(1) == 8);      // expected-warning{{FALSE}} expected-warning{{TRUE}}
 }
 
+extern int testDefParmIncompleteImport(int);
+
 int main() {
   clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}}
   clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}}
@@ -144,4 +146,6 @@
   clang_analyzer_eval(extSubSCN.a == 1); // expected-warning{{TRUE}}
   // clang_analyzer_eval(extSCC.a == 7); // TODO
   clang_analyzer_eval(extU.a == 4); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(testDefParmIncompleteImport(9) == 9); // expected-warning{{TRUE}}
 }
Index: clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
===================================================================
--- clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
+++ clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
@@ -25,3 +25,4 @@
 c:@extSubSCN ctu-other.cpp.ast
 c:@extSCC ctu-other.cpp.ast
 c:@extU ctu-other.cpp.ast
+c:@F@testDefParmIncompleteImport#I# ctu-other.cpp.ast
Index: clang/test/Analysis/Inputs/ctu-other.cpp
===================================================================
--- clang/test/Analysis/Inputs/ctu-other.cpp
+++ clang/test/Analysis/Inputs/ctu-other.cpp
@@ -131,3 +131,22 @@
   const unsigned int b;
 };
 U extU = {.a = 4};
+
+struct DefParmContext {
+  static const int I;
+  int f();
+};
+
+int fDefParm(int I = DefParmContext::I) {
+  return I;
+}
+
+int testDefParmIncompleteImport(int I) {
+  return fDefParm(I);
+}
+
+const int DefParmContext::I = 0;
+
+int DefParmContext::f() {
+  return fDefParm();
+}
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -3842,6 +3842,15 @@
   else
     return Imp.takeError();
 
+  Expr *DefaultArg = nullptr;
+  if (D->hasUninstantiatedDefaultArg()) {
+    if (Error Err = importInto(DefaultArg, D->getUninstantiatedDefaultArg()))
+      return std::move(Err);
+  } else if (D->hasDefaultArg()) {
+    if (Error Err = importInto(DefaultArg, D->getDefaultArg()))
+      return std::move(Err);
+  }
+
   ParmVarDecl *ToParm;
   if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC,
                               ToInnerLocStart, ToLocation,
@@ -3853,19 +3862,12 @@
   // Set the default argument.
   ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
   ToParm->setKNRPromoted(D->isKNRPromoted());
-
   if (D->hasUninstantiatedDefaultArg()) {
-    if (auto ToDefArgOrErr = import(D->getUninstantiatedDefaultArg()))
-      ToParm->setUninstantiatedDefaultArg(*ToDefArgOrErr);
-    else
-      return ToDefArgOrErr.takeError();
+    ToParm->setUninstantiatedDefaultArg(DefaultArg);
   } else if (D->hasUnparsedDefaultArg()) {
     ToParm->setUnparsedDefaultArg();
   } else if (D->hasDefaultArg()) {
-    if (auto ToDefArgOrErr = import(D->getDefaultArg()))
-      ToParm->setDefaultArg(*ToDefArgOrErr);
-    else
-      return ToDefArgOrErr.takeError();
+    ToParm->setDefaultArg(DefaultArg);
   }
 
   if (D->isObjCMethodParameter()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to