Skip to content

[SR-2402][ClangImporter] Import nullary function macros #6530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

modocache
Copy link
Contributor

Resolves SR-2402.

Import function-like macros that take no arguments, assuming their bodies are something ClangImporter would otherwise be able to import.

  • Modify shouldIgnoreMacro such that it only ignores function-like macros if they take more than zero arguments.
  • ClangImporter's macro importing normally creates VarDecl. Modify that to create FuncDecl if the original macro is function-like.

The implementation might be gross, I'm not sure. Another problem: importing macros from another module doesn't really work. Does anyone know what I'm missing here?

Copy link
Contributor

@CodaFi CodaFi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! A couple quick comments.


// Finally, set the body.
func->setBody(BraceStmt::create(C, SourceLoc(),
ASTNode(ret),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This should implicitly convert to ASTNode. I think you want to make the array explicit

func->setBody(BraceStmt::create(C, SourceLoc(), { ret }, SourceLoc()));

return true;

// Consult the blacklist of macros to suppress.
// Consult the list of macros to suppress.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why this is changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Blacklist" is considered exclusionary in some contexts. Here it seems "list" conveys the same meaning without any unintended consequences. I was already modifying the body of this method, so I thought I'd include this comment change as well.

}

ValueDecl *
ClangImporter::Implementation::createFunction(Identifier name, DeclContext *dc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this code is pulled from ClangImporter::Implementation::createConstant, could you find a way to factor its body to call this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do, thanks!

@modocache
Copy link
Contributor Author

Thanks for the review, @CodaFi! 🙇

@jrose-apple
Copy link
Contributor

This is pretty much the approach I was going with in my first attempt, so it looks good to me. The trouble you're having with functions chaining to macros is because of ClangImporter.cpp:390: "If it's an identifier that is itself a macro, look into that macro." That is, importMacro is recursive, but you aren't keeping track of whether the outer thing is a function.

Also worried now we're going to run into the same kind of ambiguity issue as #6531—if people have been working around this in overlays, we're in trouble. I suppose we could limit this to Swift 4 mode and cross our fingers.

Don't forget to add a test for function-like macros invoking function-like macros and object-like macros invoking function-like macros.

@modocache
Copy link
Contributor Author

This is pretty much the approach I was going with in my first attempt

Oh, I'm sorry if I duplicated your work here, @jrose-apple. Was your first attempt in a pull request somewhere? I'm sorry if I missed it.

Don't forget to add a test for function-like macros invoking function-like macros and object-like macros invoking function-like macros.

Will do!

@jrose-apple
Copy link
Contributor

Oh, no, I had a partial patch from a long time ago (over a year) that I never attached to the JIRA because it didn't apply cleanly. Actually, I vaguely remember there was a problem when you actually tried to IRGen a call to one of these macros, so please include at least one execution test as well!

@modocache
Copy link
Contributor Author

I did confirm locally that a call to a function-like macro succeeded in a running program, but I'll certainly add a test. Thanks for the suggestion!

@slavapestov
Copy link
Contributor

I wonder if we need a general solution to deal with potentially source-breaking clangimporter changes like these.

@jrose-apple
Copy link
Contributor

Officially the Clang importer is part of the language and major changes should go through swift-evolution. Things like this are on the border of "major change", though.

In that sense, limiting this to Swift 4 mode is probably the correct answer, but that doesn't help cross-language compilation (i.e. Swift 4 code trying to use both Swift 3 code and imported Objective-C code).

@slavapestov
Copy link
Contributor

@swift-ci Please test

1 similar comment
@slavapestov
Copy link
Contributor

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Jan 9, 2017

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - c85005766a0b47220fc776697d4d3fee073f3aae
Test requested by - @slavapestov

@modocache
Copy link
Contributor Author

modocache commented Jan 9, 2017

(Just FYI, I plan on making the changes Jordan suggested and then getting this merged before the end of this week. I haven't forgotten about it! 😅 )

@jrose-apple
Copy link
Contributor

I think given Doug's response to #6531 it's okay to leave this on even in Swift 3 mode. We'll handle conflicts if and when they happen, under the expectation that providing the same API in an overlay would be rare.

@slavapestov
Copy link
Contributor

@modocache Do you mind adding an entry to CHANGLEOG.md as well? We have several new ClangImporter features that might affect users so I'm following up with PR authors about documenting them.

@modocache modocache force-pushed the sr-2402-import-nullary-function-macros branch from c850057 to 8761118 Compare January 12, 2017 17:08
@modocache
Copy link
Contributor Author

modocache commented Jan 12, 2017

Uploaded some changes, but still more to come.

TODO

  • Add CHANGELOG.md entry
  • Respond to code review comments
  • Keep track of whether outer macro is function-like in recursive importMacro call, in order to get the USES_MACRO_FROM_OTHER_MODULE_1_FUNC() tests working
  • Add a test that runs an executable that references a function-like macro, to ensure no bugs occur in IRGen or what not
  • Add a test for function-like macros invoking function-like macros and object-like macros invoking function-like macros Add a test that demonstrates macros invoking function-like macros are not imported

@modocache
Copy link
Contributor Author

modocache commented Jan 12, 2017

Add a test for function-like macros invoking function-like macros and object-like macros invoking function-like macros

@jrose-apple, I thought about this a bit more, and I wonder if it makes sense to punt this to a future pull request. I don't think the ClangImporter's macro code has any logic to handle a call expression, i.e.: #define foo bar() or #define baz() bork(), does it? It seems like supporting the ability to import nullary function-like macros is tangential to supporting macros that call other macros or functions.

Of course, I'd love to import any kind of macro, but I'm worried about biting off more than I can chew. If I can reduce the scope of this pull request I'd happily do so. Thoughts? 🙌

@jrose-apple
Copy link
Contributor

I think it's fine to save that feature for later, but I'd like the tests there to be sure we're not mis-importing them somehow.

@modocache
Copy link
Contributor Author

Sure thing. Right now we don't import them at all, I think the ClangImporter gives up because of the call expression on the right. I'll add a test case that demonstrates.

@modocache modocache force-pushed the sr-2402-import-nullary-function-macros branch 2 times, most recently from 6a4b455 to 7c1f4d1 Compare January 12, 2017 20:20
@modocache
Copy link
Contributor Author

@swift-ci please smoke test

return importLiteral(impl, DC, macro, name, tok, ClangN, castType);
return importLiteral(
impl, DC, macro, name, tok, ClangN, castType,
isOriginalMacroFunctionLike || macro->isFunctionLike());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is incorrect. It's only the original macro that matters, no?

Copy link
Contributor Author

@modocache modocache Jan 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absent any recursion, importLiteral is called immediately. Since isOriginalMacroFunctionLike is false by default, this means that #define FOO() 1 would be imported as a global variable, not a Swift function. So I think this is correct as is. Modifying it to only use isOriginalMacroFunctionLike causes the newly added function-like tests to fail.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, okay. I'm suspicious of cases like #define BAR FOO() but we can wait until that actually happens to fix this.

// these can be used in executables, and don't crash at runtime.

// RUN: rm -rf %t && mkdir -p %t
// RUN: %target-swiftc_driver %s -import-objc-header %S/Inputs/macro-functions.h -o %t/macro-functions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use %target-swift-build and %target-run for this, so that it works properly on iOS, and please add REQUIRES: execution_test so that it isn't run for cross-compilation cases. The test/Interpreter/ directory is probably a more appropriate place to put the test, too; we tend to cluster execution tests there.

@modocache modocache force-pushed the sr-2402-import-nullary-function-macros branch from 7c1f4d1 to e3eeb56 Compare January 12, 2017 23:32
@modocache
Copy link
Contributor Author

@swift-ci please smoke test

@@ -0,0 +1,13 @@
// Other ClangImporter tests verify that function-like C macros are imported
// into Swift so that identifiers are resolved correclty. This test verifies
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "correclty".

@modocache
Copy link
Contributor Author

I'm sure it's due to the changes I've made here, since this doesn't reproduce using master, but the macOS error is pretty wacky. Basically, when running the Swift REPL, this happens:

$ swift
***  You are running Swift's integrated REPL,  ***
***  intended for compiler and stdlib          ***
***  development and testing purposes only.    ***
***  The full REPL is built as part of LLDB.   ***
***  Type ':help' for assistance.              ***
(swift) import MapKit
(swift) foo
<REPL Input>:1:1: error: use of unresolved identifier 'foo'
foo
^~~
<unknown>:0: warning: 'cacheParamsComputed' is deprecated
<unknown>:0: warning: 'cacheAlphaComputed' is deprecated
<unknown>:0: warning: 'keepCacheWindow' is deprecated
<unknown>:0: error: 'memoryless' is unavailable
Metal.MTLCommandBufferError:55:14: note: 'memoryless' has been explicitly marked unavailable here
        case memoryless
             ^

Same thing happens when I run:

import Metal
foo

I'm looking into why this might be happening.

@gparker42
Copy link
Contributor

Those diagnostics about memoryless etc. have been seen elsewhere (rdar://29715586, running swift build using an internal Xcode build a month ago). I doubt that they are your fault, but I don't know if the cause has been found yet.

@modocache modocache force-pushed the sr-2402-import-nullary-function-macros branch from e3eeb56 to 4d4e6d8 Compare January 13, 2017 01:53
@jrose-apple
Copy link
Contributor

Typo-correction is what brings them up at all, Sema not permitting use of deprecated/unavailable constructs in deprecated/unavailable contexts is why they get diagnosed. Just hasn't been a priority.

@modocache
Copy link
Contributor Author

Should I change the REPL tests in order to prevent the failures from occurring?

I'm curious why my changes seem to have angered the beast. I'm double-checking at the moment, but I'm pretty sure these failures occur consistently on my branch, but not on master.

@jrose-apple
Copy link
Contributor

I don't immediately see what your changes would have done. It seems like they'd only bring in more declarations (macros), not remove any existing ones.

@modocache
Copy link
Contributor Author

@swift-ci please smoke test

@modocache
Copy link
Contributor Author

Ping @jrose-apple -- what would you recommend I do here: change the test so that it doesn't happen to fail? Or dig in deeper to discover why my changes are causing the failure?

If the latter, could you please share any relevant details from rdar://29715586? It's not on OpenRadar.

@jrose-apple
Copy link
Contributor

I'm still surprised your changes have anything to do with the failing tests (which unfortunately have been wiped from the public bot), so yes, I think we need to figure out what's going on.

The Radar just says that importing certain types in Metal results in us making variables like static var unavailableAlias { return unavailableOrig } where both unavailableAlias and unavailableOrig are marked unavailable. But that shouldn't happen more often in your code than before unless lookups are triggering typo-correction, which I wouldn't expect them to.

@jrose-apple
Copy link
Contributor

Well, I fixed the issue with unavailable aliases, so we won't see that particular problem anymore. I guess we can start over from there.

Resolves SR-2402.

Import function-like macros that take no arguments, assuming their
bodies are something ClangImporter would otherwise be able to import.

* Modify `shouldIgnoreMacro` such that it only ignores function-like
  macros if they take more than zero arguments.
* ClangImporter's macro importing normally creates `VarDecl`. Modify
  that to create FuncDecl if the original macro is function-like.
@modocache modocache force-pushed the sr-2402-import-nullary-function-macros branch from 4d4e6d8 to 8f7baa3 Compare February 2, 2017 18:50
@modocache
Copy link
Contributor Author

@swift-ci please test

@modocache
Copy link
Contributor Author

Sorry for letting this languish!

@swift-ci
Copy link
Contributor

swift-ci commented Feb 2, 2017

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 4d4e6d87883513608ba36e2155eeb8b29789ba34
Test requested by - @modocache

@swift-ci
Copy link
Contributor

swift-ci commented Feb 2, 2017

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 4d4e6d87883513608ba36e2155eeb8b29789ba34
Test requested by - @modocache

@modocache
Copy link
Contributor Author

Oh, maybe I angered @swift-ci by requesting a test after force pushing to my branch. I'll try again.

@modocache
Copy link
Contributor Author

@swift-ci please smoke test

@jrose-apple
Copy link
Contributor

I let it languish just as much as you did. Glad to pick it up again now.

@modocache
Copy link
Contributor Author

Hmm, looks like the same problem test failed, Interpreter/SDK/missing_imports_repl.swift.

I probably won't have a ton of time to work on this, at least for another week or so. Please feel free to grab this task from me if you'd like to make progress on it before then!

@modocache
Copy link
Contributor Author

I don't have a ton of time to work on this anymore. Still, it was a fun way to learn more about ClangImporter, so thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants